Introduction

In Assignment 1, we utilized RNASeq data from Sanghi et al.’s publication “Chromatin Accessibility Associates with Protein-RNA Correlation in Human Cancer”. The authors aimed to explore the relationship between chromatin structure and molecular phenotypes in cancer by analyzing multi-omics profiles of 87 human thyroid cancer primary tumors, metastases, and patient-matext_connectionhed normal tissue samples. Specifically, they identified a local chromatin structure that showed strong correlation with coordinated RNA and protein expression, particularly within gene-body enhancers, and claimed that local enhancers may be more important for regulating cancer gene expression than distal enhancers. Moreover, the authors found that TFs in the MAPK pathway are actively bound significantly more in tumor and metastases than in normal tissue.

We retrieved the dataset (ID GSE162515) from GEO and filtered out low counts, where we removed genes that had less than 1 count per million (cpm) in less than three samples, resulting in the exclusion of 11538 genes. Normalizing the data by TMM with the edgeR package only slightly improved the dataset’s quality since the data was already well-aligned after filtering low counts. We then used the biomaRt package with Ensembl data to map Ensembl gene IDs to HUGO gene symbols, resulting in a final dataset of 17368 unique genes after removing low counts, genes with duplicate identifiers, and genes that could not be mapped to HUGO symbols.

In Assignment 2, we analyzed the normalized count data generated from Assignment 1 by performing differential expression analysis and thresholded over-representation analysis separately for the “Tumor tissue vs. Normal tissue” and the “metastases tissue vs. Normal tissue” groups. The thresholds applied on the dataset were p value of 0.01, FDR of 0.05, and log2 fold change of 2. The results showed that upregulated genes may be more strongly associated with specific biological processes or pathways, such as regulation of mitotic cell cycle, than downregulated genes, and that there may be some shared biological processes or pathways affected by both upregulated and downregulated genes. We also found that upregulated genes are enriched for some biological functions or pathways more strongly than the overall set of differentially expressed genes in the “Met vs. Normal” group. However, the subsequent over-representation results did not strongly support the conclusions and mechanism discussed in the original paper probably due to different annotation sources used. In the original paper, the authors predicted that the tumors would have TFs that interact with the MAPK pathway and regulate gene expression in a way that is relevant to the development and progression of cancer, and indeed they found that TFs in the MAPK pathway are actively bound significantly more in tumor and metastases than in normal tissue. Transcription factors are widely know to play a role in regulating gene expresison, which would also affect mitotic cell cycle, indicating that our results support the conclusions discussed in the original paper in some way.

In this assignment, we will further investigate on our dataset and try to gain more insights into the pathways that significant genes are involved in to better understand the mechanism for human tumor. We will use non-thresholded gene enrichment analysis to obtain a more diverse portfolio of differentially expressed genes and compare the results with those from the previously performed thresholded analysis. We hope that the non-thresholded analysis results will strengthen the plausibility of our previous results and the authors’ hypothesis in the original publication. We will use the results obtained from the non-thresholded analysis to create an enrichment map network and conduct further analysis using the network.

Download Packages

In this section, we import and install the necessary packages for this assignment, in which we will conduct a differential expression analysis using the normalized dataset and a thresholded over-representation analysis.

if (!requireNamespace("BiocManager", quietly = TRUE)){
  install.packages("BiocManager")}

if (!requireNamespace("GEOmetadb", quietly = TRUE)){
  BiocManager::install("GEOmetadb")}

if (!requireNamespace("circlize", quietly = TRUE))
    install.packages("circlize")

if (!requireNamespace("GSA", quietly = TRUE))
    install.packages("GSA")

if (!requireNamespace("ComplexHeatmap", quietly = TRUE))
    BiocManager::install("ComplexHeatmap")

if (!requireNamespace("gprofiler2", quietly = TRUE))
    BiocManager::install("gprofiler2")

if (!requireNamespace("ggplot2", quietly = TRUE)){
  install.packages("ggplot2")}

if (!requireNamespace("VennDiagram", quietly = TRUE)){
  install.packages("VennDiagram")}

if (!requireNamespace("edgeR", quietly = TRUE)){
  BiocManager::install("edgeR")}

if (!requireNamespace("biomaRt", quietly = TRUE)){
  BiocManager::install("biomaRt")}

if (!requireNamespace("knitr", quietly = TRUE)){
  install.packages("knitr")}

if (!requireNamespace("GEOquery", quietly = TRUE)){
  BiocManager::install("GEOquery")}

if (!requireNamespace("Biobase", quietly = TRUE)){
  BiocManager::install("Biobase")}

if (!requireNamespace("dplyr", quietly = TRUE)){
  install.packages("dplyr")}

if (!requireNamespace("kableExtra", quietly = TRUE)){
  install.packages("kableExtra")}

if (! requireNamespace("RCurl", quietly=TRUE)) {
    install.packages("RCurl")}

Load packages

library("GEOmetadb")
library("ggplot2")
library("edgeR")
library("biomaRt")
library("ComplexHeatmap")
library("circlize")
library("dplyr")
library("GEOquery")
library("Biobase")
library("knitr")
library("kableExtra")
library("RCurl")
library("GSA")
library("VennDiagram")

Retrieve information from Assignment 1

The normalized data processed from Assignment 1 has been stored in the file named as “normalized_counts_final.txt”. We now load this data into R. The categories for the samples were saved in “samples.txt” file. We can also load it into R.

normalized_counts <- read.table("data/normalized_counts_final.txt")
samples <- read.table("data/samples.txt")

Examine the normalized dataset

The format of the normalized count dataset has already been processed in a way that can be directly used to plot the heatmap, which would be our next step.

kable(normalized_counts[1:5,1:5], format = "html")
F001.C1.T F002.C1.N F003.C1.M F004.C2.T F005.C2.N
A1BG-AS1 9.941028 4.706365 11.072142 5.9720957 3.615496
A2M 639.332343 806.127267 728.618408 565.2189214 515.208115
A2M-AS1 0.379692 2.312610 1.428664 0.6846989 2.824606
A4GALT 6.282177 14.200239 16.310575 11.2214538 9.151723
AAAS 29.512426 30.713088 28.751854 34.8055261 24.178626

Examine the samples information

There are two columns, “individuals” and “tissue type”. The “individual” column stores data of the patients who the authors took the samples from, and the “tissue type” indicates the type of the tissue, including tumors, metastases, and normal tissue.

knitr::kable(head(samples, 10),  format = "html")
individual tissue_type
F001.C1.T C1 T
F002.C1.N C1 N
F003.C1.M C1 M
F004.C2.T C2 T
F005.C2.N C2 N
F007.C3.T C3 T
F009.C4.T C4 T
F010.C4.N C4 N
F014.C5.N C5 N
F017.C7.T C7 T

Load Ranked Data from Assignment 2

In this section, we load the ranked data from Assignment 2, which generates the non-thresholded ranked datasets for “Tumor vs. Normal” group and “Metastases vs. Normal” group.

Design Model

In this section, we will create a data matrix from our dataset.

In order to perform statistical testing, we need a design matrix that defines our model. Notice that in our dataset, there are two factors:

  1. Tissue types (Normal, tumor, metastases)
  2. Patient (individual)

Hence, ideally, we would like to account for both factors in our design matrix.

Recall that we want to find the genes that are differentially expressed in the tumor and metastases samples in contrast to normal tissues, so we first factor the tissue types such that “N” type becomes the baseline/reference level. This would affect on which tissue type would be chosen as the control value (i.e. intercept) when performing model.matrix function to generate the design matrix.

# Set normal tissue type as the intercept
samples$tissue_type <- factor(samples$tissue_type)
samples$tissue_type <- relevel(samples$tissue_type, ref="N")

# Doesn't really matter for individual people, but we can set C1 as the intercept for the sake of habit.
samples$individual <- factor(samples$individual)
samples$individual <- relevel(samples$individual, ref="C1")

# Generate design matrix with both factors: individual and tissue type
model_design <- model.matrix(~ samples$individual + samples$tissue_type)

# Check the matrix
model_design[1:5,1:5]
  (Intercept) samples$individualC10 samples$individualC11 samples$individualC12 samples$individualC13
1           1                     0                     0                     0                     0
2           1                     0                     0                     0                     0
3           1                     0                     0                     0                     0
4           1                     0                     0                     0                     0
5           1                     0                     0                     0                     0

Generating Gene Lists Using edgeR

For our downstream analysis, we are going to use edgeR, which is specifically designed for RNASeq data. First, we create the base edgeR object called DGEList. The group we want to define is the tissue type.

d <- edgeR::DGEList(counts = normalized_counts, group = samples$tissue_type)

For further processing, we choose to use the quasi-likelihood models since our dataset is from an RNASeq experiment and quasi-likelihood models are best suited to handle RNASeq data.

Check Eligibility

One important underlying assumption for using the Quasi-likelihood model is that the data follows a negative binomial distribution. We need to verify that our dataset indeed meets that assumption.

To do this, we calculate the dispersion and generate the plot to visualize the mean-variance relationship.

# Calculate dispersion
d <- edgeR::estimateDisp(d, model_design)
# Generate MV plot
edgeR::plotMeanVar(d,
                   show.raw.vars = TRUE,
                   show.tagwise.vars = TRUE,
                   NBline = TRUE,
                   show.ave.raw.vars = TRUE,
                   show.binned.common.disp.vars = TRUE,
                   main = "Mean-Variance Plot for Normalized Data")
# Display legend
legend("topleft", 
       legend=c("Raw Data", "Tagwise Dispersion", "Average Raw Variances", 
                "Binned Common Dispersion", "Negative Binomial Line"), 
       col = c("grey", "lightblue", "maroon", "red", "dodgerblue2"), pch=c(1,1,4,4,NA), lty=c(0,0,0,0,1), lwd=c(1,1,1,1,2), cex=0.6)

From the MV plot, we can see that our normalized count data follows the negative binomial distribution, where it clearly aligns with the blue line indicating the negative binomial trend.


Now, we have created the design matrix and verified the assumption for the data to be negative-binomially distributed, we can proceed to the next stage of our analysis. We fit the model using our design matrix:

fit <- edgeR::glmQLFit(d, model_design)


Once we have fit the model, we can proceed to calculate differential expression. We will perform the calculation separately for Tumor vs. Normal, and Metastases vs. Normal. To ensure that the significantly differentially expressed genes are not obtained by random, we will perform correction for multiple hypothesis testing using Benjamini-Hochberg approach.

Generate Tumor vs. Normal gene list

In this section, we want to test for differential expression between the tumor samples and normal samples.

# Conduct genewise statistical tests for tumor tissue as coefficient
qlf_tn <- edgeR::glmQLFTest(fit, coef='samples$tissue_typeT')

# Extract the top DE hits ranked by PValue
qlf_tn_hits <- edgeR::topTags(qlf_tn,sort.by = "PValue", adjust.method = "BH",
                           n = nrow(normalized_counts))

# Display table of top hits
knitr::kable(head(qlf_tn_hits$table), format = "html")
logFC logCPM F PValue FDR
CLDN16 5.384950 5.772560 122.90420 0 0
LHX2 3.473253 1.701027 130.64741 0 0
HS6ST2 4.133289 4.429133 110.57323 0 0
PRR15 5.114034 5.685377 107.41459 0 0
SLIT1 4.810897 5.765108 100.52563 0 0
ABCC11 3.961639 2.420472 99.50698 0 0


Generate Metastases vs. Normal gene list

In this section, we test for differential expression between the metastasis tissues and the normal tissues.

# Conduct genewise statistical tests for metastases tissue as coefficient
qlf_mn <- edgeR::glmQLFTest(fit, coef='samples$tissue_typeM')

# Extract the top DE hits ranked by PValue
qlf_mn_hits <- edgeR::topTags(qlf_mn,sort.by = "PValue", adjust.method = "BH",
                           n = nrow(normalized_counts))

# Display table of top hits
knitr::kable(head(qlf_mn_hits$table), format = "html") %>% kableExtra::kable_styling("striped")
logFC logCPM F PValue FDR
CDH16 -6.791713 5.728732 195.1855 0 0
CWH43 -4.967247 3.916405 187.8185 0 0
CHGA -4.588762 1.320610 647.5490 0 0
CLCNKB -3.512404 3.970571 170.1807 0 0
CCDC146 -2.524562 4.409113 161.5505 0 0
APOA1 -4.051688 2.087150 160.0036 0 0
NA


Now that we have obtained the complete and not thresholded datasets as done in Assignment 2, we can move to the next step.



Non-thresholded Pathway Analysis

Tumor vs. Normal tissue

The method we use for non-thresholded pathway is GSEA, version 4.3.2 (Subramanian et al. (2005), Mootha, Lindgren, and Eriksson (2003)).

The geneset used is from Bader Lab with the latest version (i.e. retrieved by using “current_relase” in the url). This part of code would not actually be running while knitting, it is only for display purpose.

# URL for retrieving the latest version dataset from bader lab.
gmt_link <- "http://download.baderlab.org/EM_Genesets/current_release/Human/symbol/"

# Set the current working directory as the directory where the data should be saved in.
file_dir <- getwd()

# List all the files available
files <- getURL(gmt_link)
text_connection <- textConnection(files)
text_content <- readLines(text_connection)
close(text_connection)

# Get the gmt with all the pathways and no terms inferred from electronic annotations(IEA).
required <- gregexpr("(?<=<a href=\")(.*.GOBP_AllPathways_no_GO_iea.*.)(.gmt)(?=\">)", text_content,
    perl = TRUE)
gmt <- unlist(regmatches(text_content, required))

# Set the destination path for the gmt file.
dest_path <- file.path(file_dir, gmt)

# Download the file
download.file(paste(gmt_link, gmt, sep = ""), destfile = dest_path)

Then, we generate the ranked gene set. We can calculate the rank using the following formula as discussed in lecture: \[ \mathrm{rank} = (-\log_{10}p)\cdot\mathrm{sign}(\mathrm{logFC}) \]

ranked_tn_list <- data.frame(GeneName = rownames(qlf_tn_hits$table), 
                             rank = -log10(qlf_tn_hits$table$PValue) * 
                                    sign(qlf_tn_hits$table$logFC))
ranked_tn_list <- ranked_tn_list[order(ranked_tn_list$rank, decreasing = TRUE),]

Save the list in rnk file. The data will be pushed onto Github in the “data” folder, so this code chunk would not actually run.

write.table(ranked_tn_list, file = "data/ranked_tn_list.rnk", sep = "\t", 
            quote = FALSE, row.names = FALSE)

Then we move to the GSEA version 4.3.2 application on laptop to perform the non-thresholded enrichment analysis.

The parameters being used are as following: * Maximum geneset size: 200 * Minimum geneset size: 15 * Number of permutations: 1000 * No collapse

GSEA will automatically normalize the enrichment scores for variation in gene set size. However, the normalization is not very accurate for extremely small or extremely large gene sets. Thus, we want GSEA to ignore gene sets that contain fewer than 15 genes or more than 200 genes. * Maximum geneset size of 200 is used because we want to exclude the broad, generic, and non-descriptive terms. * Minimum geneset size of 15 is chosen because we do not want to exclude the specific terms that are small or ones that are not necessarily well annotated. * Gene set permutation is set to 1000 because the default values allowed for reliable p-value and does not increase much in running time.


Summarize of enrichment results.
Enrichment in upregulated genes: * 3235 out of 5978 gene sets are upregulated in upregulated genes * 930 gene sets are significant at FDR < 25% * 452 gene sets are significantly enriched at nominal pvalue < 1% * 846 gene sets are significantly enriched at nominal pvalue < 5%

The enrichment analysis results have been saved in the tsv file. We can viw the top terms for upregulated genes:

# Read from enrichment analysis results table
tn_up <- read.delim("data/tn_up.tsv", sep = "\t")

Let’s take a first look at the result:


# Display the top terms for upregulated genes:
knitr::kable(head(tn_up, 5), format = "html") %>% kableExtra::kable_styling("striped")
NAME GS.br..follow.link.to.MSigDB GS.DETAILS SIZE ES NES NOM.p.val FDR.q.val FWER.p.val RANK.AT.MAX LEADING.EDGE X
SKIN DEVELOPMENT%GOBP%GO:0043588 SKIN DEVELOPMENT%GOBP%GO:0043588 Details ... 95 0.7030882 2.464868 0 0.0000000 0.000 1957 tags=43%, list=11%, signal=48% NA
CELL JUNCTION ORGANIZATION%REACTOME DATABASE ID RELEASE 83%446728 CELL JUNCTION ORGANIZATION%REACTOME DATABASE ID RELEASE 83%446728 Details ... 76 0.6838204 2.338896 0 0.0000000 0.000 1680 tags=38%, list=10%, signal=42% NA
HALLMARK_EPITHELIAL_MESENCHYMAL_TRANSITION%MSIGDBHALLMARK%HALLMARK_EPITHELIAL_MESENCHYMAL_TRANSITION HALLMARK_EPITHELIAL_MESENCHYMAL_TRANSITION%MSIGDBHALLMARK%HALLMARK_EPITHELIAL_MESENCHYMAL_TRANSITION Details ... 148 0.6263965 2.332006 0 0.0000000 0.000 2065 tags=45%, list=12%, signal=51% NA
EPIDERMIS DEVELOPMENT%GOBP%GO:0008544 EPIDERMIS DEVELOPMENT%GOBP%GO:0008544 Details ... 130 0.6523203 2.329427 0 0.0000000 0.000 1935 tags=36%, list=11%, signal=40% NA
CELL-CELL COMMUNICATION%REACTOME DATABASE ID RELEASE 83%1500931 CELL-CELL COMMUNICATION%REACTOME DATABASE ID RELEASE 83%1500931 Details ... 106 0.6295620 2.240751 0 0.0003522 0.001 1680 tags=32%, list=10%, signal=35% NA

We can see that the top terms associated with upregulated genes are skin development, cell junction organization, hallmark epithelial mesenchymal transition and epidermis development. However, not all columns are required to be displayed. Some of them are distracting to interpret the results. We only need to extract the NAME column which indicates the pathway names, SIZE column which shows the number of genes involved in each pathway, ES and NES columns indicating the enrichment scores and the normalized enrichment score, and the FDR q-value column indicating significance.

For the NAME column, we obtain the pathway names by extracting the substring before the first “%” symbol, and the database source as the first substring after the first “%” symbol. Then only leave the required columns indicated previously.

Since the following steps would be used many times, we will write it as a function:

processGSEA <- function(file="") {
  # Check for valid input
  if (file == "") {
    print("Please provide the GSEA enrichment result file name.")
    return(invisible(NULL))
  }
  
  # Read from enrichment analysis results table
  tb <- read.delim(paste("data/", file, sep = ""), sep = "\t")
  
  # Split the name by the % symbol
  name_col <- strsplit(tb$NAME, "%")
  
  # Extract pathway names
  names <- purrr::map_chr(name_col, 1) 
  
  # Set the NAME column to the cleaned one
  tb$NAME <- names
  
  # Extract database source
  src <- purrr::map_chr(name_col, 2)
  
  # Add a source column in the table
  tb$SRC <- src
  
  # Only keep the wanted columns
  output <- tb[, c("NAME", "SRC", "SIZE", "ES", "NES", "FDR.q.val")]
  
  return(output)
}

Now we can use the above function to clean up the table.

tn_up_clean <- processGSEA("tn_up.tsv")

# Display results
knitr::kable(head(tn_up_clean), format = "html", caption = "Table 1: Top terms of upregulated genes for Tumor vs. Normal tissue comparison") %>% kableExtra::kable_styling("striped")
Table 1: Top terms of upregulated genes for Tumor vs. Normal tissue comparison
NAME SRC SIZE ES NES FDR.q.val
SKIN DEVELOPMENT GOBP 95 0.7030882 2.464868 0.0000000
CELL JUNCTION ORGANIZATION REACTOME DATABASE ID RELEASE 83 76 0.6838204 2.338896 0.0000000
HALLMARK_EPITHELIAL_MESENCHYMAL_TRANSITION MSIGDBHALLMARK 148 0.6263965 2.332006 0.0000000
EPIDERMIS DEVELOPMENT GOBP 130 0.6523203 2.329427 0.0000000
CELL-CELL COMMUNICATION REACTOME DATABASE ID RELEASE 83 106 0.6295620 2.240751 0.0003522
KERATINIZATION REACTOME DATABASE ID RELEASE 83 56 0.6923240 2.217349 0.0002935

For the downregulated genes, the summarized results are as following: * 2743 out of 5978 gene sets are upregulated in downregulated genes * 209 gene sets are significantly enriched at FDR < 25% * 183 gene sets are significantly enriched at nominal pvalue < 1% * 305 gene sets are significantly enriched at nominal pvalue < 5%

Let’s display the top terms from enrichment analysis result:


tn_down <- processGSEA("tn_down.tsv")

# Display results
knitr::kable(head(tn_down), format = "html", caption = "Table 2: Top terms of downregulated genes for Tumor vs. Normal tissue comparison") %>% kableExtra::kable_styling("striped")
Table 2: Top terms of downregulated genes for Tumor vs. Normal tissue comparison
NAME SRC SIZE ES NES FDR.q.val
CELLULAR RESPIRATION GOBP 131 -0.6658223 -2.149473 0.0000000
AEROBIC RESPIRATION GOBP 116 -0.6671742 -2.102537 0.0003343
PROTON MOTIVE FORCE-DRIVEN ATP SYNTHESIS GOBP 57 -0.7190449 -2.056065 0.0002228
PROTON MOTIVE FORCE-DRIVEN MITOCHONDRIAL ATP SYNTHESIS GOBP 53 -0.7203910 -2.051087 0.0001671
OXIDATIVE PHOSPHORYLATION GOBP 88 -0.6730317 -2.049960 0.0001337
RESPIRATORY ELECTRON TRANSPORT, ATP SYNTHESIS BY CHEMIOSMOTIC COUPLING, AND HEAT PRODUCTION BY UNCOUPLING PROTEINS. REACTOME 113 -0.6479371 -2.038460 0.0002232

Metastases vs. Normal tissue

We now perform the same steps for the Metastases vs. Normal tissue comparison. First, create the ranked gene list based on the rank formula indicated previously.

ranked_mn_list <- data.frame(GeneName = rownames(qlf_mn_hits$table), 
                             rank = -log10(qlf_mn_hits$table$PValue) * 
                                    sign(qlf_mn_hits$table$logFC))
ranked_mn_list <- ranked_mn_list[order(ranked_mn_list$rank, decreasing = TRUE),]

Then, save the list in rnk file. The data will be pushed onto Github in the “data” folder, so this code chunk would not actually run.

write.table(ranked_mn_list, file = "data/ranked_mn_list.rnk", sep = "\t", 
            quote = FALSE, row.names = FALSE)

Next, we move to the GSEA version 4.3.2 application on laptop to perform the non-thresholded enrichment analysis.

The parameters being used are as following: * Maximum geneset size: 200 * Minimum geneset size: 15 * Number of permutations: 1000 * No collapse


Summarize of enrichment results.

For the upregulated genes, the summarized results are as following: * 3618 out of 5978 gene sets are upregulated in upregulated genes * 1721 gene sets are significant at FDR < 25% * 824 gene sets are significantly enriched at nominal pvalue < 1% * 1322 gene sets are significantly enriched at nominal pvalue < 5%

The following table displays the top terms for the upregulated genes for Metastases vs. Normal tissue comparison.


mn_up <- processGSEA("mn_up.tsv")

# Display results
knitr::kable(head(mn_up), format = "html", caption = "Table 3: Top terms of upregulated genes for Metastases vs. Normal tissue comparison") %>% kableExtra::kable_styling("striped")
Table 3: Top terms of upregulated genes for Metastases vs. Normal tissue comparison
NAME SRC SIZE ES NES FDR.q.val
EUKARYOTIC TRANSLATION ELONGATION REACTOME 90 0.7101468 2.569300 0
PROTEIN SYNTHESIS: ISOLEUCINE SMPDB 78 0.7163897 2.534339 0
PROTEIN SYNTHESIS: METHIONINE PATHWHIZ 78 0.7163897 2.533224 0
PROTEIN SYNTHESIS: HISTIDINE PATHWHIZ 78 0.7163897 2.509372 0
PROTEIN SYNTHESIS: PROLINE PATHWHIZ 78 0.7163897 2.506394 0
PROTEIN SYNTHESIS: TRYPTOPHAN PATHWHIZ 78 0.7163897 2.506334 0

For the downregulated genes, the summarized results are as following: * 2360 out of 5978 gene sets are upregulated in downregulated genes * 322 gene sets are significantly enriched at FDR < 25% * 182 gene sets are significantly enriched at nominal pvalue < 1% * 386 gene sets are significantly enriched at nominal pvalue < 5%

And the top terms for the downregulated genes:

mn_down <- processGSEA("mn_down.tsv")

# Display results
knitr::kable(head(mn_down), format = "html", caption = "Table 4: Top terms of downregulated genes for Metastases vs. Normal tissue comparison") %>% kableExtra::kable_styling("striped")
Table 4: Top terms of downregulated genes for Metastases vs. Normal tissue comparison
NAME SRC SIZE ES NES FDR.q.val
CELLULAR RESPIRATION GOBP 131 -0.6861537 -2.366764 0
AEROBIC RESPIRATION GOBP 116 -0.6943687 -2.355959 0
OXIDATIVE PHOSPHORYLATION GOBP 88 -0.7055840 -2.286921 0
ELECTRON TRANSPORT CHAIN GOBP 84 -0.6828735 -2.219202 0
MITOCHONDRIAL ATP SYNTHESIS COUPLED ELECTRON TRANSPORT GOBP 67 -0.6974870 -2.214653 0
RESPIRATORY ELECTRON TRANSPORT, ATP SYNTHESIS BY CHEMIOSMOTIC COUPLING, AND HEAT PRODUCTION BY UNCOUPLING PROTEINS. REACTOME 113 -0.6572549 -2.201410 0


How do these results compare to the results from the thresholded analysis in Assignment #2? Compare qualitatively. Is this a straight forward comparison? Why or why not?

For Tumor vs. Normal tissue comparison group, the GSEA results for the upregulated genes are very similar to the thresholded analysis performed using g:Profiler in Assignment 2, where the top terms include cell junction organization, and in Assignment 2 the cell junction assembly is also listed. However, there is a large difference in the database sources where terms show up. For thresholded analysis in Assignment 2, most of the top terms returned are from GOBP data source, whereas in the non-thresholded analysis, the top terms include various data sources, including GOBP, REACTOME, and MSIGDBHALLMARK, as shown in Table 1. For the downregulated genes, the results are very similar to A2 results as well, where both the top terms are cellular respiration and aerobic respiration. Terms such as proton motive force-driven ATP synthesis also occurs to be one of the most significant terms in both analysis.

For Metastases vs. Normal tissue comparison group, the GSEA results and g:Profiler results are very different for the up-regulated genes, but are quite similar for the downregulated genes. Both cellular respiration and aerobic respiration showed up in both analysis as the top terms returned.

However, this is not a straight forward comparison because g:Profiler and GSEA use different approaches. The similarity in the the top terms is likely attributed to the significant overrepresentation of certain genes.

Visualize Gene set Enrichment Analysis in Cytoscape

In this section, we will import the results from GSEA into Cytoscape and visualize the enrichment results as a network.

Tumor vs. Normal tissue

Create Enrichment Map


1. Create an enrichment map - how many nodes and how many edges in the resulting map? What thresholds were used to create this map? Make sure to record all thresholds. Include a screenshot of your network prior to manual layout.
In Cytoscape, we used Enrichmentmap App to generate the network from GSEA results. After installing the app, we choose the Analysis Type option as GSEA, and upload the results for upregulated genes as Enrichments Pos input, and the results for downregulated genes as Enrichments Neg input. We also uploaded the corresponding GMT file which we used in GSEA enrichment analysis, as well as the ranked gene list file generated previously.

After clicking on “Show Advanced Options”, we set the parameters as the following: * FDR q-value cutoff: 0.01 * p-value cutoff: 0.05 * Edge cutoff: 0.375 * Edge filtering metric: Jaccard + Overlap combined * Parse baderlab names in GMT file: Checked

The FDR q-value and p-value cutoffs were set to be consistent with the cutoff used from Assignment 2. The “Edge cutoff” and “Edge filtering metric” options are default values in Cytoscape, with Jaccard metric measuring the intersection over union and the overlap metric measuring intersection over the minimum size.. The “Parse bader lab names in GMT file” option can provide better readability.

The network generated includes 126 nodes and 809 edges, where each node indicates a GO term our gene list may be involved in, and edges indicates the relationships among GO terms. The terms for upregulated genes are colored in red, and the terms for downregulated genes are colored in blue, as shown in Figure 1.

Network Annotation


2. Annotate your network - what parameters did you use to annotate the network. If you are using the default parameters make sure to list them as well.

To annnotate the network, we used AutoAnnotate app using the following default settings: * Prevent cluster overlap * cluster algorithm: MCL Cluster * label column: GS_DESCR * label algorithm: WordCloud: Adjacent Words * max words per label: 3 * minimum word occurence: 1 * adjacent word bonus: 8

Then we add the legend and manually layout the network to make it publication ready.

Collapse Network to Theme Network

In this section, we collapsed the network to a theme network.


3. What are the major themes present in this analysis? Do they fit with the model? Are there any novel pathways or themes?

The major themes present in this analysis inclues upregulated pathways such as endogenous peptide antigen, skin epidermis development, and the downregulated pathways such as coupled electron transport and many more as shown in Figure 3 below. It is considered to fit the model and agree with the results by the authors of the original publication, since the term “Mirna regulation of p53 pathway in prostate cancer” was also observed as an upregulated term in the theme network, which supports that the gene set do involve in cancer related pathways. There are many “p53” related themes that were shown to be upregulated in the network, which are considered novel and might provide new insights in the mechanism that would develop cancer, and are worth further investigation.

Metastases vs. Normal tissue

We now also generate the network for Metastases vs. Normal tissue group. The network includes 458 nodes and 2915 edges, which is about 3 times more nodes and edges compared to the network for Tumor vs. Normal tissue group.

Network Annotation


2. Annotate your network - what parameters did you use to annotate the network. If you are using the default parameters make sure to list them as well.

To annnotate the network, we used AutoAnnotate app using the following default settings: * Prevent cluster overlap * cluster algorithm: MCL Cluster * label column: GS_DESCR * label algorithm: WordCloud: Adjacent Words * max words per label: 3 * minimum word occurence: 1 * adjacent word bonus: 8

Then we add the legend to make it publication ready.

Collapse Network to Theme Network

In this section, we collapsed the network to a theme network.


3. What are the major themes present in this analysis? Do they fit with the model? Are there any novel pathways or themes?

The major themes are displayed in Figure 6 below. They fit the model because the major themes mathces with the top terms returned from GSEA and thresholded analysis results, such as T-cell receptor (TCR), which is the largest theme in the theme network, and the term “T-cell activation” also showed up in the thresholded analysis. This would also be considered as a novel theme because the authors did not discussed about T-cell regulation with human cancer mechanism, which is worth further investigation.

Interpretation and detailed view of results


Do the enrichment results support conclusions or mechanism discussed in the original paper? How do these results differ from the results you got from Assignment #2 thresholded methods? Can you find evidence, i.e. publications, to support some of the results that you see. How does this evidence support your result?
The enrichment results from GSEA supports the mechanism discussed in the original paper. In the original paper, the authors predicted that the tumors would have TFs that interact with the MAPK pathway and regulate gene expression in a way that is relevant to the development and progression of cancer, and indeed they found that TFs in the MAPK pathway are actively bound significantly more in tumor and metastases than in normal tissue. According to the publication “Transcriptional regulation by p53” (Beckerman and Prives (2010)), p53 is an important transcription factor that regulates hundreds of cells’ RNA polymerase II transcribed genes. By publication “The functional interactions between the p53 and MAPK signaling pathways” (S (2004)), p53 is identified as a tumor supressor protein to be functionally interact with the MAPK pathway, which further supports our results.

Post Analysis


Add a post analysis to your main network using specific transcription factors, microRNAs or drugs. Include the reason why you chose the specific miRs, TFs or drugs (i.e publications indicating that they might be related to your model). What does this post analysis show?

I am curious on the p53 related terms that showed up in the Tumor vs. Normal tissue comparison and would like to investigate whether the increased amount of TFs the authors detected in experiment were actually p53 in the tumor samples, so I will use p53 as the TF to perform a Post (Known Signatures) analysis on our network. I chose p53 because it was a transcriptional factor involved in MAPK pathway, which is related to cancer, as indicated from the publication “The functional interactions between the p53 and MAPK signaling pathways” (S (2004)).

Within Cytoscape EnrichmentMap app, we downloaded the current release of human symbol transcription factors GMT file, and then select only the following two signature gene sets since we are only interested in p53: * P53_02.v2023.1.Hs * P53_DECAMER_Q2.v2023.1.Hs

We used the Mann-Whitney (Two-Sided) testing with 0.01 cutoff to investigate whether the genes in the signature sets were found mostly at the bottom or the top of our ranked gene list.

The network generated is shown below, where the terms P53 TRANSCRIPTIONAL GENE NETWORK, DIRECT P53 EFFECTORS and HALLMARK ALLOGRAFT REJECTION are linked to the two signature gene sets.

From the network, we can see that the linked target terms are highly significant to the signature data sets, with a significance level of < 0.01. A gene named “FAS” is noticable, where it is one of the top three genes ranked in all three terms, as shown in Table 5.

direct_p53 <- read.table("data/direct_p53_effectors.txt", sep = "\t", header = TRUE)

# Display results
knitr::kable(head(direct_p53), format = "html", caption = "Table 5: (a) Top ranked genes for the term DIRECT P53 EFFECTORS. FAS gene is highlighted as one of the top genes in the list.") %>% 
  kableExtra::kable_styling("striped") %>% 
  kableExtra::row_spec(3, background = "yellow")
Table 5: (a) Top ranked genes for the term DIRECT P53 EFFECTORS. FAS gene is highlighted as one of the top genes in the list.
Gene Description Ranks Tumor.vs.Normal
BID BID 11.81 1
TGFA TGFA 10.73 1
FAS FAS 10.43 1
GDF15 GDF15 9.71 1
TNFRSF10B TNFRSF10B 9.19 1
DDB2 DDB2 9.12 1
p53_tgn <- read.table("data/p53_transcriptional_gene_network.txt", sep = "\t", header = TRUE)

# Display results
knitr::kable(head(p53_tgn), format = "html", caption = "Table 5: (b) Top ranked genes for the term DP53 TRANSCRIPTIONAL GENE NETWORK. FAS gene is highlighted as one of the top genes in the list.") %>% 
  kableExtra::kable_styling("striped") %>% 
  kableExtra::row_spec(2, background = "yellow")
Table 5: (b) Top ranked genes for the term DP53 TRANSCRIPTIONAL GENE NETWORK. FAS gene is highlighted as one of the top genes in the list.
Gene Description Ranks Tumor.vs.Normal
ZMAT3 ZMAT3 10.49 1
FAS FAS 10.43 1
DDB2 DDB2 9.12 1
BBC3 BBC3 8.78 1
GLS2 GLS2 8.26 1
BAX BAX 6.87 1
hallmark <- read.table("data/hallmark_allograft_rejection.txt", sep = "\t", header = TRUE)

# Display results
knitr::kable(head(hallmark), format = "html", caption = "Table 5: (c) Top ranked genes for the term HALLMARK ALLOGRAFT REJECTION. FAS gene is highlighted as one of the top genes in the list.") %>% 
  kableExtra::kable_styling("striped") %>% 
  kableExtra::row_spec(1, background = "yellow")
Table 5: (c) Top ranked genes for the term HALLMARK ALLOGRAFT REJECTION. FAS gene is highlighted as one of the top genes in the list.
Gene Description Ranks Tumor.vs.Normal
FAS FAS 10.43 1
TIMP1 TIMP1 9.75 1
EREG EREG 8.10 1
TGFB1 TGFB1 7.25 1
CCND2 CCND2 6.67 1
FLNA FLNA 6.44 1

FAS gene is the apoptosis-mediating surface antigen, which targets Tumor Ncrosis Factor Receptor Superfamily. According to the publication “Regulation of the p53 transcriptional response by structurally diverse core promoters” (Morachis, Murawsky, and Emerson (2010)), p53 target promoters are structurally diverse and display pronounced differences in RNA polymerase II (RNAP II) occupancy with high level of FAS genes in unstressed cells. Since it was discussed that p53 is an important transcriptional factor involved in MAPK pathway which might cause cancer for its miss-functioning, focusing more on the FAS gene and the p53 mechanism may provide further insights on designing therapies.

References

Beckerman, R., and C. Prives. 2010. “Transcriptional Regulation by P53.” Cold Spring Harbor Perspectives in Biology 2 (8): 000935. https://doi.org/10.1101/cshperspect.a000935.
Chen, Hanbo. 2022. VennDiagram: Generate High-Resolution Venn and Euler Plots. https://CRAN.R-project.org/package=VennDiagram.
Chen, Y., A. T. L. Lun, and G. K. Smyth. 2016. “From Reads to Genes to Pathways: Differential Expression Analysis of RNA-Seq Experiments Using Rsubread and the edgeR Quasi-Likelihood Pipeline.”
Davis, S., and P. Meltzer. 2007. “GEOquery: A Bridge Between the Gene Expression Omnibus (GEO) and BioConductor.” Bioinformatics 14: 1846–47.
Durinck, S., Y. Moreau, A. Kasprzyk, S. Davis, B. Moor, A. Brazma, and W. Huber. 2005. “BioMart and Bioconductor: A Powerful Link Between Biological Databases and Microarray Data Analysis.” Bioinformatics 21: 3439–40.
Durinck, S., P. Spellman, E. Birney, and W. Huber. 2009. “Mapping Identifiers for the Integration of Genomic Datasets with the r/Bioconductor Package biomaRt.” Nature Protocols 4: 1184–91.
Efron, Brad, and R. Tibshirani. 2022. GSA: Gene Set Analysis. https://CRAN.R-project.org/package=GSA.
Gu, Z., R. Eils, and M. Schlesner. 2016. “Complex Heatmaps Reveal Patterns and Correlations in Multidimensional Genomic Data.” Bioinformatics. https://doi.org/10.1093/bioinformatics/btw313.
Gu, Z., L. Gu, R. Eils, M. Schlesner, and B. Brors. 2014. “Circlize Implements and Enhances Circular Visualization in r.” Bioinformatics 30: 2811–12.
Huber, W., V. J. Carey, R. Gentleman, S. Anders, M. Carlson, B. S. Carvalho, H. C. Bravo, et al. 2015. “Orchestrating High-Throughput Genomic Analysis with Bioconductor.” Nature Methods 12 (2): 115–21.
McCarthy, D. J., Chen Y, and G. K. Smyth. 2012. “Differential Expression Analysis of Multifactor RNA-Seq Experiments with Respect to Biological Variation.” Nucleic Acids Research 40: 4288–97.
Mootha, V., C. Lindgren, and K. F. Eriksson. 2003. “PGC-1α-Responsive Genes Involved in Oxidative Phosphorylation Are Coordinately Downregulated in Human Diabetes.” Nat Genet 34: 267–73. https://doi.org/10.1038/ng1180.
Morachis, J. M., C. M. Murawsky, and B. M. Emerson. 2010. “Regulation of the P53 Transcriptional Response by Structurally Diverse Core Promoters.” Genes & Development 24 (2): 135–47. https://doi.org/10.1101/gad.1856710.
Morgan, Martin. 2021. “BiocManager: Access the Bioconductor Project Package Repository.”
R Core Team. 2022. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.
Robinson, M. D., McCarthy DJ, and G. K. Smyth. 2010. “edgeR: A Bioconductor Package for Differential Expression Analysis of Digital Gene Expression Data.” Bioinformatics 26: 139–40.
S, Wu G. 2004. “The Functional Interactions Between the P53 and MAPK Signaling Pathways.” Cancer Biology & Therapy 3 (2): 156–61. https://doi.org/10.4161/cbt.3.2.614.
Subramanian, Aravind, Pablo Tamayo, Vamsi K. Mootha, Sayan Mukherjee, Benjamin L. Ebert, Michael A. Gillette, Amanda Paulovich, et al. 2005. “Gene Set Enrichment Analysis: A Knowledge-Based Approach for Interpreting Genome-Wide Expression Profiles.” Proceedings of the National Academy of Sciences 102 (43): 15545–50. https://doi.org/10.1073/pnas.0506580102.
Temple Lang, Duncan. 2023. RCurl: General Network (HTTP/FTP/...) Client Interface for r. https://CRAN.R-project.org/package=RCurl.
LS0tCnRpdGxlOiAiQXNzaWdubWVudCAzIgphdXRob3I6ICJDaGVuZ1l1ZSBaaGFuZyIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAnMicKICAgIGRmX3ByaW50OiBwYWdlZAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAyCiAgcGRmX2RvY3VtZW50OgogICAgZmlnX2NhcHRpb246IHllcwpiaWJsaW9ncmFwaHk6IGRhdGEvQTMuYmliCmFsd2F5c19hbGxvd19odG1sOiB5ZXMKLS0tCgojIEludHJvZHVjdGlvbgoKSW4gQXNzaWdubWVudCAxLCB3ZSB1dGlsaXplZCBSTkFTZXEgZGF0YSBmcm9tIFNhbmdoaSBldCBhbC4ncyBwdWJsaWNhdGlvbiAiQ2hyb21hdGluIEFjY2Vzc2liaWxpdHkgQXNzb2NpYXRlcyB3aXRoIFByb3RlaW4tUk5BIENvcnJlbGF0aW9uIGluIEh1bWFuIENhbmNlciIuIFRoZSBhdXRob3JzIGFpbWVkIHRvIGV4cGxvcmUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGNocm9tYXRpbiBzdHJ1Y3R1cmUgYW5kIG1vbGVjdWxhciBwaGVub3R5cGVzIGluIGNhbmNlciBieSBhbmFseXppbmcgbXVsdGktb21pY3MgcHJvZmlsZXMgb2YgODcgaHVtYW4gdGh5cm9pZCBjYW5jZXIgcHJpbWFyeSB0dW1vcnMsIG1ldGFzdGFzZXMsIGFuZCBwYXRpZW50LW1hdGV4dF9jb25uZWN0aW9uaGVkIG5vcm1hbCB0aXNzdWUgc2FtcGxlcy4gU3BlY2lmaWNhbGx5LCB0aGV5IGlkZW50aWZpZWQgYSBsb2NhbCBjaHJvbWF0aW4gc3RydWN0dXJlIHRoYXQgc2hvd2VkIHN0cm9uZyBjb3JyZWxhdGlvbiB3aXRoIGNvb3JkaW5hdGVkIFJOQSBhbmQgcHJvdGVpbiBleHByZXNzaW9uLCBwYXJ0aWN1bGFybHkgd2l0aGluIGdlbmUtYm9keSBlbmhhbmNlcnMsIGFuZCBjbGFpbWVkIHRoYXQgbG9jYWwgZW5oYW5jZXJzIG1heSBiZSBtb3JlIGltcG9ydGFudCBmb3IgcmVndWxhdGluZyBjYW5jZXIgZ2VuZSBleHByZXNzaW9uIHRoYW4gZGlzdGFsIGVuaGFuY2Vycy4gTW9yZW92ZXIsIHRoZSBhdXRob3JzIGZvdW5kIHRoYXQgVEZzIGluIHRoZSBNQVBLIHBhdGh3YXkgYXJlIGFjdGl2ZWx5IGJvdW5kIHNpZ25pZmljYW50bHkgbW9yZSBpbiB0dW1vciBhbmQgbWV0YXN0YXNlcyB0aGFuIGluIG5vcm1hbCB0aXNzdWUuIAoKV2UgcmV0cmlldmVkIHRoZSBkYXRhc2V0IChJRCBHU0UxNjI1MTUpIGZyb20gR0VPIGFuZCBmaWx0ZXJlZCBvdXQgbG93IGNvdW50cywgd2hlcmUgd2UgcmVtb3ZlZCBnZW5lcyB0aGF0IGhhZCBsZXNzIHRoYW4gMSBjb3VudCBwZXIgbWlsbGlvbiAoY3BtKSBpbiBsZXNzIHRoYW4gdGhyZWUgc2FtcGxlcywgcmVzdWx0aW5nIGluIHRoZSBleGNsdXNpb24gb2YgMTE1MzggZ2VuZXMuIE5vcm1hbGl6aW5nIHRoZSBkYXRhIGJ5IFRNTSB3aXRoIHRoZSBlZGdlUiBwYWNrYWdlIG9ubHkgc2xpZ2h0bHkgaW1wcm92ZWQgdGhlIGRhdGFzZXQncyBxdWFsaXR5IHNpbmNlIHRoZSBkYXRhIHdhcyBhbHJlYWR5IHdlbGwtYWxpZ25lZCBhZnRlciBmaWx0ZXJpbmcgbG93IGNvdW50cy4gV2UgdGhlbiB1c2VkIHRoZSBiaW9tYVJ0IHBhY2thZ2Ugd2l0aCBFbnNlbWJsIGRhdGEgdG8gbWFwIEVuc2VtYmwgZ2VuZSBJRHMgdG8gSFVHTyBnZW5lIHN5bWJvbHMsIHJlc3VsdGluZyBpbiBhIGZpbmFsIGRhdGFzZXQgb2YgMTczNjggdW5pcXVlIGdlbmVzIGFmdGVyIHJlbW92aW5nIGxvdyBjb3VudHMsIGdlbmVzIHdpdGggZHVwbGljYXRlIGlkZW50aWZpZXJzLCBhbmQgZ2VuZXMgdGhhdCBjb3VsZCBub3QgYmUgbWFwcGVkIHRvIEhVR08gc3ltYm9scy4KCkluIEFzc2lnbm1lbnQgMiwgd2UgYW5hbHl6ZWQgdGhlIG5vcm1hbGl6ZWQgY291bnQgZGF0YSBnZW5lcmF0ZWQgZnJvbSBBc3NpZ25tZW50IDEgYnkgcGVyZm9ybWluZyBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyBhbmQgdGhyZXNob2xkZWQgb3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcyBzZXBhcmF0ZWx5IGZvciB0aGUgIlR1bW9yIHRpc3N1ZSB2cy4gTm9ybWFsIHRpc3N1ZSIgYW5kIHRoZSAibWV0YXN0YXNlcyB0aXNzdWUgdnMuIE5vcm1hbCB0aXNzdWUiIGdyb3Vwcy4gVGhlIHRocmVzaG9sZHMgYXBwbGllZCBvbiB0aGUgZGF0YXNldCB3ZXJlIHAgdmFsdWUgb2YgMC4wMSwgRkRSIG9mIDAuMDUsIGFuZCBsb2cyIGZvbGQgY2hhbmdlIG9mIDIuIFRoZSByZXN1bHRzIHNob3dlZCB0aGF0IHVwcmVndWxhdGVkIGdlbmVzIG1heSBiZSBtb3JlIHN0cm9uZ2x5IGFzc29jaWF0ZWQgd2l0aCBzcGVjaWZpYyBiaW9sb2dpY2FsIHByb2Nlc3NlcyBvciBwYXRod2F5cywgc3VjaCBhcyByZWd1bGF0aW9uIG9mIG1pdG90aWMgY2VsbCBjeWNsZSwgdGhhbiBkb3ducmVndWxhdGVkIGdlbmVzLCBhbmQgdGhhdCB0aGVyZSBtYXkgYmUgc29tZSBzaGFyZWQgYmlvbG9naWNhbCBwcm9jZXNzZXMgb3IgcGF0aHdheXMgYWZmZWN0ZWQgYnkgYm90aCB1cHJlZ3VsYXRlZCBhbmQgZG93bnJlZ3VsYXRlZCBnZW5lcy4gV2UgYWxzbyBmb3VuZCB0aGF0IHVwcmVndWxhdGVkIGdlbmVzIGFyZSBlbnJpY2hlZCBmb3Igc29tZSBiaW9sb2dpY2FsIGZ1bmN0aW9ucyBvciBwYXRod2F5cyBtb3JlIHN0cm9uZ2x5IHRoYW4gdGhlIG92ZXJhbGwgc2V0IG9mIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBpbiB0aGUgIk1ldCB2cy4gTm9ybWFsIiBncm91cC4gSG93ZXZlciwgdGhlIHN1YnNlcXVlbnQgb3Zlci1yZXByZXNlbnRhdGlvbiByZXN1bHRzIGRpZCBub3Qgc3Ryb25nbHkgc3VwcG9ydCB0aGUgY29uY2x1c2lvbnMgYW5kIG1lY2hhbmlzbSBkaXNjdXNzZWQgaW4gdGhlIG9yaWdpbmFsIHBhcGVyIHByb2JhYmx5IGR1ZSB0byBkaWZmZXJlbnQgYW5ub3RhdGlvbiBzb3VyY2VzIHVzZWQuIEluIHRoZSBvcmlnaW5hbCBwYXBlciwgdGhlIGF1dGhvcnMgcHJlZGljdGVkIHRoYXQgdGhlIHR1bW9ycyB3b3VsZCBoYXZlIFRGcyB0aGF0IGludGVyYWN0IHdpdGggdGhlIE1BUEsgcGF0aHdheSBhbmQgcmVndWxhdGUgZ2VuZSBleHByZXNzaW9uIGluIGEgd2F5IHRoYXQgaXMgcmVsZXZhbnQgdG8gdGhlIGRldmVsb3BtZW50IGFuZCBwcm9ncmVzc2lvbiBvZiBjYW5jZXIsIGFuZCBpbmRlZWQgdGhleSBmb3VuZCB0aGF0IFRGcyBpbiB0aGUgTUFQSyBwYXRod2F5IGFyZSBhY3RpdmVseSBib3VuZCBzaWduaWZpY2FudGx5IG1vcmUgaW4gdHVtb3IgYW5kIG1ldGFzdGFzZXMgdGhhbiBpbiBub3JtYWwgdGlzc3VlLiBUcmFuc2NyaXB0aW9uIGZhY3RvcnMgYXJlIHdpZGVseSBrbm93IHRvIHBsYXkgYSByb2xlIGluIHJlZ3VsYXRpbmcgZ2VuZSBleHByZXNpc29uLCB3aGljaCB3b3VsZCBhbHNvIGFmZmVjdCBtaXRvdGljIGNlbGwgY3ljbGUsIGluZGljYXRpbmcgdGhhdCBvdXIgcmVzdWx0cyBzdXBwb3J0IHRoZSBjb25jbHVzaW9ucyBkaXNjdXNzZWQgaW4gdGhlIG9yaWdpbmFsIHBhcGVyIGluIHNvbWUgd2F5LgoKSW4gdGhpcyBhc3NpZ25tZW50LCB3ZSB3aWxsIGZ1cnRoZXIgaW52ZXN0aWdhdGUgb24gb3VyIGRhdGFzZXQgYW5kIHRyeSB0byBnYWluIG1vcmUgaW5zaWdodHMgaW50byB0aGUgcGF0aHdheXMgdGhhdCBzaWduaWZpY2FudCBnZW5lcyBhcmUgaW52b2x2ZWQgaW4gdG8gYmV0dGVyIHVuZGVyc3RhbmQgdGhlIG1lY2hhbmlzbSBmb3IgaHVtYW4gdHVtb3IuIFdlIHdpbGwgdXNlIG5vbi10aHJlc2hvbGRlZCBnZW5lIGVucmljaG1lbnQgYW5hbHlzaXMgdG8gb2J0YWluIGEgbW9yZSBkaXZlcnNlIHBvcnRmb2xpbyBvZiBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgYW5kIGNvbXBhcmUgdGhlIHJlc3VsdHMgd2l0aCB0aG9zZSBmcm9tIHRoZSBwcmV2aW91c2x5IHBlcmZvcm1lZCB0aHJlc2hvbGRlZCBhbmFseXNpcy4gV2UgaG9wZSB0aGF0IHRoZSBub24tdGhyZXNob2xkZWQgYW5hbHlzaXMgcmVzdWx0cyB3aWxsIHN0cmVuZ3RoZW4gdGhlIHBsYXVzaWJpbGl0eSBvZiBvdXIgcHJldmlvdXMgcmVzdWx0cyBhbmQgdGhlIGF1dGhvcnPigJkgaHlwb3RoZXNpcyBpbiB0aGUgb3JpZ2luYWwgcHVibGljYXRpb24uIFdlIHdpbGwgdXNlIHRoZSByZXN1bHRzIG9idGFpbmVkIGZyb20gdGhlIG5vbi10aHJlc2hvbGRlZCBhbmFseXNpcyB0byBjcmVhdGUgYW4gZW5yaWNobWVudCBtYXAgbmV0d29yayBhbmQgY29uZHVjdCBmdXJ0aGVyIGFuYWx5c2lzIHVzaW5nIHRoZSBuZXR3b3JrLgoKCiMgRG93bmxvYWQgUGFja2FnZXMKSW4gdGhpcyBzZWN0aW9uLCB3ZSBpbXBvcnQgYW5kIGluc3RhbGwgdGhlIG5lY2Vzc2FyeSBwYWNrYWdlcyBmb3IgdGhpcyBhc3NpZ25tZW50LCBpbiB3aGljaCB3ZSB3aWxsIGNvbmR1Y3QgYSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyB1c2luZyB0aGUgbm9ybWFsaXplZCBkYXRhc2V0IGFuZCBhIHRocmVzaG9sZGVkIG92ZXItcmVwcmVzZW50YXRpb24gYW5hbHlzaXMuCgoqIFIgKEByKQoqIFtCaW9jTWFuYWdlcl0oaHR0cHM6Ly9DUkFOLlItcHJvamVjdC5vcmcvcGFja2FnZT1CaW9jTWFuYWdlcikgKEBtb3JnYW4yMDIxYSkKKiBbR0VPbWV0YWRiXShodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL2h0bWwvR0VPbWV0YWRiLmh0bWwpIChAbWNjYXJ0aHkyMDEyYSkKKiBbZWRnZVJdKGh0dHBzOi8vYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9yZWxlYXNlL2Jpb2MvaHRtbC9lZGdlUi5odG1sKSAoQHJvYmluc29uMjAxMGEsIEBtY2NhcnRoeTIwMTJhLCBAY2hlbjIwMTZhKQoqIFtiaW9tYVJ0XShodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL2h0bWwvYmlvbWFSdC5odG1sKSAoQGR1cmluY2syMDA5YSwgQGR1cmluY2syMDA1YSkKKiBbR0VPcXVlcnldKGh0dHBzOi8vYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9yZWxlYXNlL2Jpb2MvaHRtbC9HRU9xdWVyeS5odG1sKSAoQGRhdmlzMjAwN2EpCiogW0dTQV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL0dTQS9pbmRleC5odG1sKSAoQEdTQSkKKiBbQmlvYmFzZSAmIEJpb0dlbmVyaWNzXShodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL2h0bWwvQmlvYmFzZS5odG1sKSAoQGh1YmVyMjAxNWEpCiogW2NpcmNsaXplXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvY2lyY2xpemUvaW5kZXguaHRtbCkgKEBndTIwMTRhKQoqIFtDb21wbGV4SGVhdG1hcF0oaHR0cHM6Ly9iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2UvYmlvYy9odG1sL0NvbXBsZXhIZWF0bWFwLmh0bWwpIChAZ3UyMDE2YSkKKiBbUkN1cmxdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9SQ3VybC9pbmRleC5odG1sKSAoQHJjdXJsKQoqIFtWZW5uRGlhZ3JhbV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL1Zlbm5EaWFncmFtL2luZGV4Lmh0bWwpIChAVmVubikKCmBgYHtyIEluc3RhbGwgcGFja2FnZXMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmlmICghcmVxdWlyZU5hbWVzcGFjZSgiQmlvY01hbmFnZXIiLCBxdWlldGx5ID0gVFJVRSkpewogIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIil9CgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkdFT21ldGFkYiIsIHF1aWV0bHkgPSBUUlVFKSl7CiAgQmlvY01hbmFnZXI6Omluc3RhbGwoIkdFT21ldGFkYiIpfQoKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJjaXJjbGl6ZSIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIGluc3RhbGwucGFja2FnZXMoImNpcmNsaXplIikKCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiR1NBIiwgcXVpZXRseSA9IFRSVUUpKQogICAgaW5zdGFsbC5wYWNrYWdlcygiR1NBIikKCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiQ29tcGxleEhlYXRtYXAiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiQ29tcGxleEhlYXRtYXAiKQoKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJncHJvZmlsZXIyIiwgcXVpZXRseSA9IFRSVUUpKQogICAgQmlvY01hbmFnZXI6Omluc3RhbGwoImdwcm9maWxlcjIiKQoKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJnZ3Bsb3QyIiwgcXVpZXRseSA9IFRSVUUpKXsKICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIil9CgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIlZlbm5EaWFncmFtIiwgcXVpZXRseSA9IFRSVUUpKXsKICBpbnN0YWxsLnBhY2thZ2VzKCJWZW5uRGlhZ3JhbSIpfQoKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJlZGdlUiIsIHF1aWV0bHkgPSBUUlVFKSl7CiAgQmlvY01hbmFnZXI6Omluc3RhbGwoImVkZ2VSIil9CgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImJpb21hUnQiLCBxdWlldGx5ID0gVFJVRSkpewogIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJiaW9tYVJ0Iil9CgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImtuaXRyIiwgcXVpZXRseSA9IFRSVUUpKXsKICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpfQoKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJHRU9xdWVyeSIsIHF1aWV0bHkgPSBUUlVFKSl7CiAgQmlvY01hbmFnZXI6Omluc3RhbGwoIkdFT3F1ZXJ5Iil9CgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkJpb2Jhc2UiLCBxdWlldGx5ID0gVFJVRSkpewogIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJCaW9iYXNlIil9CgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImRwbHlyIiwgcXVpZXRseSA9IFRSVUUpKXsKICBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpfQoKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJrYWJsZUV4dHJhIiwgcXVpZXRseSA9IFRSVUUpKXsKICBpbnN0YWxsLnBhY2thZ2VzKCJrYWJsZUV4dHJhIil9CgppZiAoISByZXF1aXJlTmFtZXNwYWNlKCJSQ3VybCIsIHF1aWV0bHk9VFJVRSkpIHsKICAgIGluc3RhbGwucGFja2FnZXMoIlJDdXJsIil9CmBgYAoKTG9hZCBwYWNrYWdlcwpgYGB7ciBMb2FkIGxpYnJhcnksIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkoIkdFT21ldGFkYiIpCmxpYnJhcnkoImdncGxvdDIiKQpsaWJyYXJ5KCJlZGdlUiIpCmxpYnJhcnkoImJpb21hUnQiKQpsaWJyYXJ5KCJDb21wbGV4SGVhdG1hcCIpCmxpYnJhcnkoImNpcmNsaXplIikKbGlicmFyeSgiZHBseXIiKQpsaWJyYXJ5KCJHRU9xdWVyeSIpCmxpYnJhcnkoIkJpb2Jhc2UiKQpsaWJyYXJ5KCJrbml0ciIpCmxpYnJhcnkoImthYmxlRXh0cmEiKQpsaWJyYXJ5KCJSQ3VybCIpCmxpYnJhcnkoIkdTQSIpCmxpYnJhcnkoIlZlbm5EaWFncmFtIikKYGBgCgojIFJldHJpZXZlIGluZm9ybWF0aW9uIGZyb20gQXNzaWdubWVudCAxClRoZSBub3JtYWxpemVkIGRhdGEgcHJvY2Vzc2VkIGZyb20gQXNzaWdubWVudCAxIGhhcyBiZWVuIHN0b3JlZCBpbiB0aGUgZmlsZSBuYW1lZCBhcyAibm9ybWFsaXplZF9jb3VudHNfZmluYWwudHh0Ii4gV2Ugbm93IGxvYWQgdGhpcyBkYXRhIGludG8gUi4KVGhlIGNhdGVnb3JpZXMgZm9yIHRoZSBzYW1wbGVzIHdlcmUgc2F2ZWQgaW4gInNhbXBsZXMudHh0IiBmaWxlLiBXZSBjYW4gYWxzbyBsb2FkIGl0IGludG8gUi4KYGBge3IgcmV0cmlldmVfZGF0YSwgbWVzc2FnZT1GQUxTRX0Kbm9ybWFsaXplZF9jb3VudHMgPC0gcmVhZC50YWJsZSgiZGF0YS9ub3JtYWxpemVkX2NvdW50c19maW5hbC50eHQiKQpzYW1wbGVzIDwtIHJlYWQudGFibGUoImRhdGEvc2FtcGxlcy50eHQiKQpgYGAKCiMjIEV4YW1pbmUgdGhlIG5vcm1hbGl6ZWQgZGF0YXNldApUaGUgZm9ybWF0IG9mIHRoZSBub3JtYWxpemVkIGNvdW50IGRhdGFzZXQgaGFzIGFscmVhZHkgYmVlbiBwcm9jZXNzZWQgaW4gYSB3YXkgdGhhdCBjYW4gYmUgZGlyZWN0bHkgdXNlZCB0byBwbG90IHRoZSBoZWF0bWFwLCB3aGljaCB3b3VsZCBiZSBvdXIgbmV4dCBzdGVwLgpgYGB7ciBjaGVja19kYXRhLCBtZXNzYWdlPUZBTFNFfQprYWJsZShub3JtYWxpemVkX2NvdW50c1sxOjUsMTo1XSwgZm9ybWF0ID0gImh0bWwiKQpgYGAKCiMjIEV4YW1pbmUgdGhlIHNhbXBsZXMgaW5mb3JtYXRpb24KClRoZXJlIGFyZSB0d28gY29sdW1ucywgImluZGl2aWR1YWxzIiBhbmQgInRpc3N1ZSB0eXBlIi4gVGhlICJpbmRpdmlkdWFsIiBjb2x1bW4gc3RvcmVzIGRhdGEgb2YgdGhlIHBhdGllbnRzIHdobyB0aGUgYXV0aG9ycyB0b29rIHRoZSBzYW1wbGVzIGZyb20sIGFuZCB0aGUgInRpc3N1ZSB0eXBlIiBpbmRpY2F0ZXMgdGhlIHR5cGUgb2YgdGhlIHRpc3N1ZSwgaW5jbHVkaW5nIHR1bW9ycywgbWV0YXN0YXNlcywgYW5kIG5vcm1hbCB0aXNzdWUuCmBgYHtyIHNhbXBsZXN9CmtuaXRyOjprYWJsZShoZWFkKHNhbXBsZXMsIDEwKSwgIGZvcm1hdCA9ICJodG1sIikKYGBgCgojIExvYWQgUmFua2VkIERhdGEgZnJvbSBBc3NpZ25tZW50IDIKSW4gdGhpcyBzZWN0aW9uLCB3ZSBsb2FkIHRoZSByYW5rZWQgZGF0YSBmcm9tIEFzc2lnbm1lbnQgMiwgd2hpY2ggZ2VuZXJhdGVzIHRoZSBub24tdGhyZXNob2xkZWQgcmFua2VkIGRhdGFzZXRzIGZvciAiVHVtb3IgdnMuIE5vcm1hbCIgZ3JvdXAgYW5kICJNZXRhc3Rhc2VzIHZzLiBOb3JtYWwiIGdyb3VwLgoKIyMgRGVzaWduIE1vZGVsCkluIHRoaXMgc2VjdGlvbiwgd2Ugd2lsbCBjcmVhdGUgYSBkYXRhIG1hdHJpeCBmcm9tIG91ciBkYXRhc2V0LgoKCkluIG9yZGVyIHRvIHBlcmZvcm0gc3RhdGlzdGljYWwgdGVzdGluZywgd2UgbmVlZCBhIGRlc2lnbiBtYXRyaXggdGhhdCBkZWZpbmVzIG91ciBtb2RlbC4gTm90aWNlIHRoYXQgaW4gb3VyIGRhdGFzZXQsIHRoZXJlIGFyZSB0d28gZmFjdG9yczogCgoxLiBUaXNzdWUgdHlwZXMgKE5vcm1hbCwgdHVtb3IsIG1ldGFzdGFzZXMpCjIuIFBhdGllbnQgKGluZGl2aWR1YWwpCgpIZW5jZSwgaWRlYWxseSwgd2Ugd291bGQgbGlrZSB0byBhY2NvdW50IGZvciBib3RoIGZhY3RvcnMgaW4gb3VyIGRlc2lnbiBtYXRyaXguCgpSZWNhbGwgdGhhdCB3ZSB3YW50IHRvIGZpbmQgdGhlIGdlbmVzIHRoYXQgYXJlIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBpbiB0aGUgdHVtb3IgYW5kIG1ldGFzdGFzZXMgc2FtcGxlcyBpbiBjb250cmFzdCB0byBub3JtYWwgdGlzc3Vlcywgc28gd2UgZmlyc3QgZmFjdG9yIHRoZSB0aXNzdWUgdHlwZXMgc3VjaCB0aGF0ICJOIiB0eXBlIGJlY29tZXMgdGhlIGJhc2VsaW5lL3JlZmVyZW5jZSBsZXZlbC4gVGhpcyB3b3VsZCBhZmZlY3Qgb24gd2hpY2ggdGlzc3VlIHR5cGUgd291bGQgYmUgY2hvc2VuIGFzIHRoZSBjb250cm9sIHZhbHVlIChpLmUuIGludGVyY2VwdCkgd2hlbiBwZXJmb3JtaW5nIF9fKiptb2RlbC5tYXRyaXgqKl9fIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIHRoZSBkZXNpZ24gbWF0cml4LgoKYGBge3IgZGVzaWduX21hdHJpeCwgbWVzc2FnZT1GQUxTRX0KIyBTZXQgbm9ybWFsIHRpc3N1ZSB0eXBlIGFzIHRoZSBpbnRlcmNlcHQKc2FtcGxlcyR0aXNzdWVfdHlwZSA8LSBmYWN0b3Ioc2FtcGxlcyR0aXNzdWVfdHlwZSkKc2FtcGxlcyR0aXNzdWVfdHlwZSA8LSByZWxldmVsKHNhbXBsZXMkdGlzc3VlX3R5cGUsIHJlZj0iTiIpCgojIERvZXNuJ3QgcmVhbGx5IG1hdHRlciBmb3IgaW5kaXZpZHVhbCBwZW9wbGUsIGJ1dCB3ZSBjYW4gc2V0IEMxIGFzIHRoZSBpbnRlcmNlcHQgZm9yIHRoZSBzYWtlIG9mIGhhYml0LgpzYW1wbGVzJGluZGl2aWR1YWwgPC0gZmFjdG9yKHNhbXBsZXMkaW5kaXZpZHVhbCkKc2FtcGxlcyRpbmRpdmlkdWFsIDwtIHJlbGV2ZWwoc2FtcGxlcyRpbmRpdmlkdWFsLCByZWY9IkMxIikKCiMgR2VuZXJhdGUgZGVzaWduIG1hdHJpeCB3aXRoIGJvdGggZmFjdG9yczogaW5kaXZpZHVhbCBhbmQgdGlzc3VlIHR5cGUKbW9kZWxfZGVzaWduIDwtIG1vZGVsLm1hdHJpeCh+IHNhbXBsZXMkaW5kaXZpZHVhbCArIHNhbXBsZXMkdGlzc3VlX3R5cGUpCgojIENoZWNrIHRoZSBtYXRyaXgKbW9kZWxfZGVzaWduWzE6NSwxOjVdCmBgYAoKCiMjIEdlbmVyYXRpbmcgR2VuZSBMaXN0cyBVc2luZyBlZGdlUgoKRm9yIG91ciBkb3duc3RyZWFtIGFuYWx5c2lzLCB3ZSBhcmUgZ29pbmcgdG8gdXNlIGVkZ2VSLCB3aGljaCBpcyBzcGVjaWZpY2FsbHkgZGVzaWduZWQgZm9yIFJOQVNlcSBkYXRhLiBGaXJzdCwgd2UgY3JlYXRlIHRoZSBiYXNlIGVkZ2VSIG9iamVjdCBjYWxsZWQgREdFTGlzdC4gVGhlIGdyb3VwIHdlIHdhbnQgdG8gZGVmaW5lIGlzIHRoZSB0aXNzdWUgdHlwZS4gCmBgYHtyIGRpc3BlcnNpb25fY2FsYywgbWVzc2FnZT1GQUxTRX0KZCA8LSBlZGdlUjo6REdFTGlzdChjb3VudHMgPSBub3JtYWxpemVkX2NvdW50cywgZ3JvdXAgPSBzYW1wbGVzJHRpc3N1ZV90eXBlKQpgYGAKRm9yIGZ1cnRoZXIgcHJvY2Vzc2luZywgd2UgY2hvb3NlIHRvIHVzZSB0aGUgcXVhc2ktbGlrZWxpaG9vZCBtb2RlbHMgc2luY2Ugb3VyIGRhdGFzZXQgaXMgZnJvbSBhbiBSTkFTZXEgZXhwZXJpbWVudCBhbmQgcXVhc2ktbGlrZWxpaG9vZCBtb2RlbHMgYXJlIGJlc3Qgc3VpdGVkIHRvIGhhbmRsZSBSTkFTZXEgZGF0YS4KCiMjIyBDaGVjayBFbGlnaWJpbGl0eQoKT25lIGltcG9ydGFudCB1bmRlcmx5aW5nIGFzc3VtcHRpb24gZm9yIHVzaW5nIHRoZSBRdWFzaS1saWtlbGlob29kIG1vZGVsIGlzIHRoYXQgdGhlIGRhdGEgZm9sbG93cyBhIG5lZ2F0aXZlIGJpbm9taWFsIGRpc3RyaWJ1dGlvbi4gV2UgbmVlZCB0byB2ZXJpZnkgdGhhdCBvdXIgZGF0YXNldCBpbmRlZWQgbWVldHMgdGhhdCBhc3N1bXB0aW9uLgoKVG8gZG8gdGhpcywgd2UgY2FsY3VsYXRlIHRoZSBkaXNwZXJzaW9uIGFuZCBnZW5lcmF0ZSB0aGUgcGxvdCB0byB2aXN1YWxpemUgdGhlIG1lYW4tdmFyaWFuY2UgcmVsYXRpb25zaGlwLiAKCmBgYHtyIGVzdGltYXRlX2Rpc3AsIG1lc3NhZ2UgPSBGQUxTRX0KIyBDYWxjdWxhdGUgZGlzcGVyc2lvbgpkIDwtIGVkZ2VSOjplc3RpbWF0ZURpc3AoZCwgbW9kZWxfZGVzaWduKQpgYGAKCmBgYHtyIG1lYW5fdmFyX3Bsb3QsIGV2YWwgPSBGQUxTRX0KIyBHZW5lcmF0ZSBNViBwbG90CmVkZ2VSOjpwbG90TWVhblZhcihkLAogICAgICAgICAgICAgICAgICAgc2hvdy5yYXcudmFycyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICBzaG93LnRhZ3dpc2UudmFycyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICBOQmxpbmUgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgc2hvdy5hdmUucmF3LnZhcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgc2hvdy5iaW5uZWQuY29tbW9uLmRpc3AudmFycyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICBtYWluID0gIk1lYW4tVmFyaWFuY2UgUGxvdCBmb3IgTm9ybWFsaXplZCBEYXRhIikKIyBEaXNwbGF5IGxlZ2VuZApsZWdlbmQoInRvcGxlZnQiLCAKICAgICAgIGxlZ2VuZD1jKCJSYXcgRGF0YSIsICJUYWd3aXNlIERpc3BlcnNpb24iLCAiQXZlcmFnZSBSYXcgVmFyaWFuY2VzIiwgCiAgICAgICAgICAgICAgICAiQmlubmVkIENvbW1vbiBEaXNwZXJzaW9uIiwgIk5lZ2F0aXZlIEJpbm9taWFsIExpbmUiKSwgCiAgICAgICBjb2wgPSBjKCJncmV5IiwgImxpZ2h0Ymx1ZSIsICJtYXJvb24iLCAicmVkIiwgImRvZGdlcmJsdWUyIiksIHBjaD1jKDEsMSw0LDQsTkEpLCBsdHk9YygwLDAsMCwwLDEpLCBsd2Q9YygxLDEsMSwxLDIpLCBjZXg9MC42KQpgYGAKCkZyb20gdGhlIE1WIHBsb3QsIHdlIGNhbiBzZWUgdGhhdCBvdXIgbm9ybWFsaXplZCBjb3VudCBkYXRhIGZvbGxvd3MgdGhlIG5lZ2F0aXZlIGJpbm9taWFsIGRpc3RyaWJ1dGlvbiwgd2hlcmUgaXQgY2xlYXJseSBhbGlnbnMgd2l0aCB0aGUgYmx1ZSBsaW5lIGluZGljYXRpbmcgdGhlIG5lZ2F0aXZlIGJpbm9taWFsIHRyZW5kLgoKYGBge3IgbWVhbl92YXJfZGlzcGxheSwgb3V0LndpZHRoID0gIjkwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmNhcD0iRmlndXJlIDMuIE1lYW4tdmFyaWFuY2UgcGxvdCBzaG93aW5nIHRoZSBkaXN0cmlidXRpb24gb2YgZGF0YS4gVGhlIGRpc3BlcnNpb24gYW5kIHZhcmlhbmNlIG9mIHRoZSBkYXRhIHBlcmZlY3RseSBmb2xsb3dzIHRoZSBuZWdhdGl2ZSBiaW5vbWlhbCBkaXN0cmlidXRpb24sIGluIHdoaWNoIHRoZSByYXcgZGF0YSBhbmQgdGhlIGJsdWUgbmVnYXRpdmUgYmlub21pYWwgbGluZSBhbGxpZ25zLiJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJmaWd1cmVzL21lYW5fdmFyLmpwZyIpCmBgYAoKPGJyPgoKTm93LCB3ZSBoYXZlIGNyZWF0ZWQgdGhlIGRlc2lnbiBtYXRyaXggYW5kIHZlcmlmaWVkIHRoZSBhc3N1bXB0aW9uIGZvciB0aGUgZGF0YSB0byBiZSBuZWdhdGl2ZS1iaW5vbWlhbGx5IGRpc3RyaWJ1dGVkLCB3ZSBjYW4gcHJvY2VlZCB0byB0aGUgbmV4dCBzdGFnZSBvZiBvdXIgYW5hbHlzaXMuIFdlIGZpdCB0aGUgbW9kZWwgdXNpbmcgb3VyIGRlc2lnbiBtYXRyaXg6IAoKYGBge3IgZml0X3FsLCBtZXNzYWdlPUZBTFNFfQpmaXQgPC0gZWRnZVI6OmdsbVFMRml0KGQsIG1vZGVsX2Rlc2lnbikKYGBgCjxicj4KCk9uY2Ugd2UgaGF2ZSBmaXQgdGhlIG1vZGVsLCB3ZSBjYW4gcHJvY2VlZCB0byBjYWxjdWxhdGUgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24uIFdlIHdpbGwgcGVyZm9ybSB0aGUgY2FsY3VsYXRpb24gc2VwYXJhdGVseSBmb3IgX18qKlR1bW9yIHZzLiBOb3JtYWwqKl9fLCBhbmQgX18qKk1ldGFzdGFzZXMgdnMuIE5vcm1hbCoqX18uIFRvIGVuc3VyZSB0aGF0IHRoZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhcmUgbm90IG9idGFpbmVkIGJ5IHJhbmRvbSwgd2Ugd2lsbCBwZXJmb3JtICBjb3JyZWN0aW9uIGZvciBtdWx0aXBsZSBoeXBvdGhlc2lzIHRlc3RpbmcgdXNpbmcgQmVuamFtaW5pLUhvY2hiZXJnIGFwcHJvYWNoLgoKIyMgR2VuZXJhdGUgVHVtb3IgdnMuIE5vcm1hbCBnZW5lIGxpc3QKCkluIHRoaXMgc2VjdGlvbiwgd2Ugd2FudCB0byB0ZXN0IGZvciBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBiZXR3ZWVuIHRoZSB0dW1vciBzYW1wbGVzIGFuZCBub3JtYWwgc2FtcGxlcy4KYGBge3IgdGVzdF90biwgbWVzc2FnZT1GQUxTRX0KIyBDb25kdWN0IGdlbmV3aXNlIHN0YXRpc3RpY2FsIHRlc3RzIGZvciB0dW1vciB0aXNzdWUgYXMgY29lZmZpY2llbnQKcWxmX3RuIDwtIGVkZ2VSOjpnbG1RTEZUZXN0KGZpdCwgY29lZj0nc2FtcGxlcyR0aXNzdWVfdHlwZVQnKQoKIyBFeHRyYWN0IHRoZSB0b3AgREUgaGl0cyByYW5rZWQgYnkgUFZhbHVlCnFsZl90bl9oaXRzIDwtIGVkZ2VSOjp0b3BUYWdzKHFsZl90bixzb3J0LmJ5ID0gIlBWYWx1ZSIsIGFkanVzdC5tZXRob2QgPSAiQkgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBuID0gbnJvdyhub3JtYWxpemVkX2NvdW50cykpCgojIERpc3BsYXkgdGFibGUgb2YgdG9wIGhpdHMKa25pdHI6OmthYmxlKGhlYWQocWxmX3RuX2hpdHMkdGFibGUpLCBmb3JtYXQgPSAiaHRtbCIpCmBgYAo8YnI+CgoKIyMgR2VuZXJhdGUgTWV0YXN0YXNlcyB2cy4gTm9ybWFsIGdlbmUgbGlzdAoKSW4gdGhpcyBzZWN0aW9uLCB3ZSB0ZXN0IGZvciBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBiZXR3ZWVuIHRoZSBtZXRhc3Rhc2lzIHRpc3N1ZXMgYW5kIHRoZSBub3JtYWwgdGlzc3Vlcy4KYGBge3IgdGVzdF9tbiwgbWVzc2FnZT1GQUxTRX0KIyBDb25kdWN0IGdlbmV3aXNlIHN0YXRpc3RpY2FsIHRlc3RzIGZvciBtZXRhc3Rhc2VzIHRpc3N1ZSBhcyBjb2VmZmljaWVudApxbGZfbW4gPC0gZWRnZVI6OmdsbVFMRlRlc3QoZml0LCBjb2VmPSdzYW1wbGVzJHRpc3N1ZV90eXBlTScpCgojIEV4dHJhY3QgdGhlIHRvcCBERSBoaXRzIHJhbmtlZCBieSBQVmFsdWUKcWxmX21uX2hpdHMgPC0gZWRnZVI6OnRvcFRhZ3MocWxmX21uLHNvcnQuYnkgPSAiUFZhbHVlIiwgYWRqdXN0Lm1ldGhvZCA9ICJCSCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSBucm93KG5vcm1hbGl6ZWRfY291bnRzKSkKCiMgRGlzcGxheSB0YWJsZSBvZiB0b3AgaGl0cwprbml0cjo6a2FibGUoaGVhZChxbGZfbW5faGl0cyR0YWJsZSksIGZvcm1hdCA9ICJodG1sIikgJT4lIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoInN0cmlwZWQiKQoKYGBgCjxicj4KCk5vdyB0aGF0IHdlIGhhdmUgb2J0YWluZWQgdGhlIGNvbXBsZXRlIGFuZCBub3QgdGhyZXNob2xkZWQgZGF0YXNldHMgYXMgZG9uZSBpbiBBc3NpZ25tZW50IDIsIHdlIGNhbiBtb3ZlIHRvIHRoZSBuZXh0IHN0ZXAuCgoqKioKCjxicj4KCiMgTm9uLXRocmVzaG9sZGVkIFBhdGh3YXkgQW5hbHlzaXMKCiMjIFR1bW9yIHZzLiBOb3JtYWwgdGlzc3VlCgpUaGUgbWV0aG9kIHdlIHVzZSBmb3Igbm9uLXRocmVzaG9sZGVkIHBhdGh3YXkgaXMgR1NFQSwgdmVyc2lvbiA0LjMuMiAoQGdzZWExLCBAbW9vdGhhMjAwM2EpLgoKVGhlIGdlbmVzZXQgdXNlZCBpcyBmcm9tIEJhZGVyIExhYiB3aXRoIHRoZSBsYXRlc3QgdmVyc2lvbiAoaS5lLiByZXRyaWV2ZWQgYnkgdXNpbmcgImN1cnJlbnRfcmVsYXNlIiBpbiB0aGUgdXJsKS4gVGhpcyBwYXJ0IG9mIGNvZGUgd291bGQgbm90IGFjdHVhbGx5IGJlIHJ1bm5pbmcgd2hpbGUga25pdHRpbmcsIGl0IGlzIG9ubHkgZm9yIGRpc3BsYXkgcHVycG9zZS4KCmBgYHtyIGJhZGVyX2xhYl9kYXRhc2V0LCBldmFsID0gRkFMU0V9CiMgVVJMIGZvciByZXRyaWV2aW5nIHRoZSBsYXRlc3QgdmVyc2lvbiBkYXRhc2V0IGZyb20gYmFkZXIgbGFiLgpnbXRfbGluayA8LSAiaHR0cDovL2Rvd25sb2FkLmJhZGVybGFiLm9yZy9FTV9HZW5lc2V0cy9jdXJyZW50X3JlbGVhc2UvSHVtYW4vc3ltYm9sLyIKCiMgU2V0IHRoZSBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5IGFzIHRoZSBkaXJlY3Rvcnkgd2hlcmUgdGhlIGRhdGEgc2hvdWxkIGJlIHNhdmVkIGluLgpmaWxlX2RpciA8LSBnZXR3ZCgpCgojIExpc3QgYWxsIHRoZSBmaWxlcyBhdmFpbGFibGUKZmlsZXMgPC0gZ2V0VVJMKGdtdF9saW5rKQp0ZXh0X2Nvbm5lY3Rpb24gPC0gdGV4dENvbm5lY3Rpb24oZmlsZXMpCnRleHRfY29udGVudCA8LSByZWFkTGluZXModGV4dF9jb25uZWN0aW9uKQpjbG9zZSh0ZXh0X2Nvbm5lY3Rpb24pCgojIEdldCB0aGUgZ210IHdpdGggYWxsIHRoZSBwYXRod2F5cyBhbmQgbm8gdGVybXMgaW5mZXJyZWQgZnJvbSBlbGVjdHJvbmljIGFubm90YXRpb25zKElFQSkuCnJlcXVpcmVkIDwtIGdyZWdleHByKCIoPzw9PGEgaHJlZj1cIikoLiouR09CUF9BbGxQYXRod2F5c19ub19HT19pZWEuKi4pKC5nbXQpKD89XCI+KSIsIHRleHRfY29udGVudCwKICAgIHBlcmwgPSBUUlVFKQpnbXQgPC0gdW5saXN0KHJlZ21hdGNoZXModGV4dF9jb250ZW50LCByZXF1aXJlZCkpCgojIFNldCB0aGUgZGVzdGluYXRpb24gcGF0aCBmb3IgdGhlIGdtdCBmaWxlLgpkZXN0X3BhdGggPC0gZmlsZS5wYXRoKGZpbGVfZGlyLCBnbXQpCgojIERvd25sb2FkIHRoZSBmaWxlCmRvd25sb2FkLmZpbGUocGFzdGUoZ210X2xpbmssIGdtdCwgc2VwID0gIiIpLCBkZXN0ZmlsZSA9IGRlc3RfcGF0aCkKYGBgCgpUaGVuLCB3ZSBnZW5lcmF0ZSB0aGUgcmFua2VkIGdlbmUgc2V0LiBXZSBjYW4gY2FsY3VsYXRlIHRoZSByYW5rIHVzaW5nIHRoZSBmb2xsb3dpbmcgZm9ybXVsYSBhcyBkaXNjdXNzZWQgaW4gbGVjdHVyZToKJCQKXG1hdGhybXtyYW5rfSA9ICgtXGxvZ197MTB9cClcY2RvdFxtYXRocm17c2lnbn0oXG1hdGhybXtsb2dGQ30pCiQkCgpgYGB7ciBjcmVhdGUgcmFua2VkIGdlbmUgbGlzdCBmb3IgVCB2cyBOLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgbWVzc2FnZT1GQUxTRX0KcmFua2VkX3RuX2xpc3QgPC0gZGF0YS5mcmFtZShHZW5lTmFtZSA9IHJvd25hbWVzKHFsZl90bl9oaXRzJHRhYmxlKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuayA9IC1sb2cxMChxbGZfdG5faGl0cyR0YWJsZSRQVmFsdWUpICogCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpZ24ocWxmX3RuX2hpdHMkdGFibGUkbG9nRkMpKQpyYW5rZWRfdG5fbGlzdCA8LSByYW5rZWRfdG5fbGlzdFtvcmRlcihyYW5rZWRfdG5fbGlzdCRyYW5rLCBkZWNyZWFzaW5nID0gVFJVRSksXQpgYGAKClNhdmUgdGhlIGxpc3QgaW4gcm5rIGZpbGUuIFRoZSBkYXRhIHdpbGwgYmUgcHVzaGVkIG9udG8gR2l0aHViIGluIHRoZSAiZGF0YSIgZm9sZGVyLCBzbyB0aGlzIGNvZGUgY2h1bmsgd291bGQgbm90IGFjdHVhbGx5IHJ1bi4KYGBge3Igb3V0cHV0IHJhbmtlZCB0biBsaXN0LCBldmFsID0gRkFMU0V9CndyaXRlLnRhYmxlKHJhbmtlZF90bl9saXN0LCBmaWxlID0gImRhdGEvcmFua2VkX3RuX2xpc3Qucm5rIiwgc2VwID0gIlx0IiwgCiAgICAgICAgICAgIHF1b3RlID0gRkFMU0UsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKClRoZW4gd2UgbW92ZSB0byB0aGUgR1NFQSB2ZXJzaW9uIDQuMy4yIGFwcGxpY2F0aW9uIG9uIGxhcHRvcCB0byBwZXJmb3JtIHRoZSBub24tdGhyZXNob2xkZWQgZW5yaWNobWVudCBhbmFseXNpcy4KCgpUaGUgcGFyYW1ldGVycyBiZWluZyB1c2VkIGFyZSBhcyBmb2xsb3dpbmc6CiogTWF4aW11bSBnZW5lc2V0IHNpemU6IDIwMAoqIE1pbmltdW0gZ2VuZXNldCBzaXplOiAxNQoqIE51bWJlciBvZiBwZXJtdXRhdGlvbnM6IDEwMDAKKiBObyBjb2xsYXBzZQoKR1NFQSB3aWxsIGF1dG9tYXRpY2FsbHkgbm9ybWFsaXplIHRoZSBlbnJpY2htZW50IHNjb3JlcyBmb3IgdmFyaWF0aW9uIGluIGdlbmUgc2V0IHNpemUuIEhvd2V2ZXIsIHRoZSBub3JtYWxpemF0aW9uIGlzIG5vdCB2ZXJ5IGFjY3VyYXRlIGZvciBleHRyZW1lbHkgc21hbGwgb3IgZXh0cmVtZWx5IGxhcmdlIGdlbmUgc2V0cy4gVGh1cywgd2Ugd2FudCBHU0VBIHRvIGlnbm9yZSBnZW5lIHNldHMgdGhhdCBjb250YWluIGZld2VyIHRoYW4gMTUgZ2VuZXMgb3IgbW9yZSB0aGFuIDIwMCBnZW5lcy4gCiogTWF4aW11bSBnZW5lc2V0IHNpemUgb2YgMjAwIGlzIHVzZWQgYmVjYXVzZSB3ZSB3YW50IHRvIGV4Y2x1ZGUgdGhlIGJyb2FkLCBnZW5lcmljLCBhbmQgbm9uLWRlc2NyaXB0aXZlIHRlcm1zLiAKKiBNaW5pbXVtIGdlbmVzZXQgc2l6ZSBvZiAxNSBpcyBjaG9zZW4gYmVjYXVzZSB3ZSBkbyBub3Qgd2FudCB0byBleGNsdWRlIHRoZSBzcGVjaWZpYyB0ZXJtcyB0aGF0IGFyZSBzbWFsbCBvciBvbmVzIHRoYXQgYXJlIG5vdCBuZWNlc3NhcmlseSB3ZWxsIGFubm90YXRlZC4gCiogR2VuZSBzZXQgcGVybXV0YXRpb24gaXMgc2V0IHRvIDEwMDAgYmVjYXVzZSB0aGUgZGVmYXVsdCB2YWx1ZXMgYWxsb3dlZCBmb3IgcmVsaWFibGUgcC12YWx1ZSBhbmQgZG9lcyBub3QgaW5jcmVhc2UgbXVjaCBpbiBydW5uaW5nIHRpbWUuCgo8YnI+Cl9fKipTdW1tYXJpemUgb2YgZW5yaWNobWVudCByZXN1bHRzLioqX18KPGJyPgpFbnJpY2htZW50IGluIHVwcmVndWxhdGVkIGdlbmVzOgoqIDMyMzUgb3V0IG9mIDU5NzggZ2VuZSBzZXRzIGFyZSB1cHJlZ3VsYXRlZCBpbiB1cHJlZ3VsYXRlZCBnZW5lcwoqIDkzMCBnZW5lIHNldHMgYXJlIHNpZ25pZmljYW50IGF0IEZEUiA8IDI1JQoqIDQ1MiBnZW5lIHNldHMgYXJlIHNpZ25pZmljYW50bHkgZW5yaWNoZWQgYXQgbm9taW5hbCBwdmFsdWUgPCAxJQoqIDg0NiBnZW5lIHNldHMgYXJlIHNpZ25pZmljYW50bHkgZW5yaWNoZWQgYXQgbm9taW5hbCBwdmFsdWUgPCA1JQoKVGhlIGVucmljaG1lbnQgYW5hbHlzaXMgcmVzdWx0cyBoYXZlIGJlZW4gc2F2ZWQgaW4gdGhlIHRzdiBmaWxlLiBXZSBjYW4gdml3IHRoZSB0b3AgdGVybXMgZm9yIHVwcmVndWxhdGVkIGdlbmVzOgpgYGB7ciB0bl91cCwgbWVzc2FnZT1GQUxTRX0KIyBSZWFkIGZyb20gZW5yaWNobWVudCBhbmFseXNpcyByZXN1bHRzIHRhYmxlCnRuX3VwIDwtIHJlYWQuZGVsaW0oImRhdGEvdG5fdXAudHN2Iiwgc2VwID0gIlx0IikKYGBgCgpMZXQncyB0YWtlIGEgZmlyc3QgbG9vayBhdCB0aGUgcmVzdWx0OgpgYGB7ciB0bl91cCBmaXJzdCBkaXNwbGF5LCBtZXNzYWdlPUZBTFNFfQoKIyBEaXNwbGF5IHRoZSB0b3AgdGVybXMgZm9yIHVwcmVndWxhdGVkIGdlbmVzOgprbml0cjo6a2FibGUoaGVhZCh0bl91cCwgNSksIGZvcm1hdCA9ICJodG1sIikgJT4lIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoInN0cmlwZWQiKQpgYGAKCldlIGNhbiBzZWUgdGhhdCB0aGUgdG9wIHRlcm1zIGFzc29jaWF0ZWQgd2l0aCB1cHJlZ3VsYXRlZCBnZW5lcyBhcmUgc2tpbiBkZXZlbG9wbWVudCwgY2VsbCBqdW5jdGlvbiBvcmdhbml6YXRpb24sIGhhbGxtYXJrIGVwaXRoZWxpYWwgbWVzZW5jaHltYWwgdHJhbnNpdGlvbiBhbmQgZXBpZGVybWlzIGRldmVsb3BtZW50LiBIb3dldmVyLCBub3QgYWxsIGNvbHVtbnMgYXJlIHJlcXVpcmVkIHRvIGJlIGRpc3BsYXllZC4gU29tZSBvZiB0aGVtIGFyZSBkaXN0cmFjdGluZyB0byBpbnRlcnByZXQgdGhlIHJlc3VsdHMuIFdlIG9ubHkgbmVlZCB0byBleHRyYWN0IHRoZSBOQU1FIGNvbHVtbiB3aGljaCBpbmRpY2F0ZXMgdGhlIHBhdGh3YXkgbmFtZXMsIFNJWkUgY29sdW1uIHdoaWNoIHNob3dzIHRoZSBudW1iZXIgb2YgZ2VuZXMgaW52b2x2ZWQgaW4gZWFjaCBwYXRod2F5LCBFUyBhbmQgTkVTIGNvbHVtbnMgaW5kaWNhdGluZyB0aGUgZW5yaWNobWVudCBzY29yZXMgYW5kIHRoZSBub3JtYWxpemVkIGVucmljaG1lbnQgc2NvcmUsIGFuZCB0aGUgRkRSIHEtdmFsdWUgY29sdW1uIGluZGljYXRpbmcgc2lnbmlmaWNhbmNlLgoKRm9yIHRoZSBOQU1FIGNvbHVtbiwgd2Ugb2J0YWluIHRoZSBwYXRod2F5IG5hbWVzIGJ5IGV4dHJhY3RpbmcgdGhlIHN1YnN0cmluZyBiZWZvcmUgdGhlIGZpcnN0ICIlIiBzeW1ib2wsIGFuZCB0aGUgZGF0YWJhc2Ugc291cmNlIGFzIHRoZSBmaXJzdCBzdWJzdHJpbmcgYWZ0ZXIgdGhlIGZpcnN0ICIlIiBzeW1ib2wuIFRoZW4gb25seSBsZWF2ZSB0aGUgcmVxdWlyZWQgY29sdW1ucyBpbmRpY2F0ZWQgcHJldmlvdXNseS4KClNpbmNlIHRoZSBmb2xsb3dpbmcgc3RlcHMgd291bGQgYmUgdXNlZCBtYW55IHRpbWVzLCB3ZSB3aWxsIHdyaXRlIGl0IGFzIGEgZnVuY3Rpb246CmBgYHtyIGdzZWFfcHJvY2VzcywgbWVzc2FnZSA9IEZBTFNFfQpwcm9jZXNzR1NFQSA8LSBmdW5jdGlvbihmaWxlPSIiKSB7CiAgIyBDaGVjayBmb3IgdmFsaWQgaW5wdXQKICBpZiAoZmlsZSA9PSAiIikgewogICAgcHJpbnQoIlBsZWFzZSBwcm92aWRlIHRoZSBHU0VBIGVucmljaG1lbnQgcmVzdWx0IGZpbGUgbmFtZS4iKQogICAgcmV0dXJuKGludmlzaWJsZShOVUxMKSkKICB9CiAgCiAgIyBSZWFkIGZyb20gZW5yaWNobWVudCBhbmFseXNpcyByZXN1bHRzIHRhYmxlCiAgdGIgPC0gcmVhZC5kZWxpbShwYXN0ZSgiZGF0YS8iLCBmaWxlLCBzZXAgPSAiIiksIHNlcCA9ICJcdCIpCiAgCiAgIyBTcGxpdCB0aGUgbmFtZSBieSB0aGUgJSBzeW1ib2wKICBuYW1lX2NvbCA8LSBzdHJzcGxpdCh0YiROQU1FLCAiJSIpCiAgCiAgIyBFeHRyYWN0IHBhdGh3YXkgbmFtZXMKICBuYW1lcyA8LSBwdXJycjo6bWFwX2NocihuYW1lX2NvbCwgMSkgCiAgCiAgIyBTZXQgdGhlIE5BTUUgY29sdW1uIHRvIHRoZSBjbGVhbmVkIG9uZQogIHRiJE5BTUUgPC0gbmFtZXMKICAKICAjIEV4dHJhY3QgZGF0YWJhc2Ugc291cmNlCiAgc3JjIDwtIHB1cnJyOjptYXBfY2hyKG5hbWVfY29sLCAyKQogIAogICMgQWRkIGEgc291cmNlIGNvbHVtbiBpbiB0aGUgdGFibGUKICB0YiRTUkMgPC0gc3JjCiAgCiAgIyBPbmx5IGtlZXAgdGhlIHdhbnRlZCBjb2x1bW5zCiAgb3V0cHV0IDwtIHRiWywgYygiTkFNRSIsICJTUkMiLCAiU0laRSIsICJFUyIsICJORVMiLCAiRkRSLnEudmFsIildCiAgCiAgcmV0dXJuKG91dHB1dCkKfQpgYGAKCk5vdyB3ZSBjYW4gdXNlIHRoZSBhYm92ZSBmdW5jdGlvbiB0byBjbGVhbiB1cCB0aGUgdGFibGUuCmBgYHtyIHRuX3VwIGNsZWFudXAsIG1lc3NhZ2U9RkFMU0V9CnRuX3VwX2NsZWFuIDwtIHByb2Nlc3NHU0VBKCJ0bl91cC50c3YiKQoKIyBEaXNwbGF5IHJlc3VsdHMKa25pdHI6OmthYmxlKGhlYWQodG5fdXBfY2xlYW4pLCBmb3JtYXQgPSAiaHRtbCIsIGNhcHRpb24gPSAiVGFibGUgMTogVG9wIHRlcm1zIG9mIHVwcmVndWxhdGVkIGdlbmVzIGZvciBUdW1vciB2cy4gTm9ybWFsIHRpc3N1ZSBjb21wYXJpc29uIikgJT4lIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoInN0cmlwZWQiKQpgYGAKCkZvciB0aGUgZG93bnJlZ3VsYXRlZCBnZW5lcywgdGhlIHN1bW1hcml6ZWQgcmVzdWx0cyBhcmUgYXMgZm9sbG93aW5nOgoqIDI3NDMgb3V0IG9mIDU5NzggZ2VuZSBzZXRzIGFyZSB1cHJlZ3VsYXRlZCBpbiBkb3ducmVndWxhdGVkIGdlbmVzCiogMjA5IGdlbmUgc2V0cyBhcmUgc2lnbmlmaWNhbnRseSBlbnJpY2hlZCBhdCBGRFIgPCAyNSUKKiAxODMgZ2VuZSBzZXRzIGFyZSBzaWduaWZpY2FudGx5IGVucmljaGVkIGF0IG5vbWluYWwgcHZhbHVlIDwgMSUKKiAzMDUgZ2VuZSBzZXRzIGFyZSBzaWduaWZpY2FudGx5IGVucmljaGVkIGF0IG5vbWluYWwgcHZhbHVlIDwgNSUKCkxldCdzIGRpc3BsYXkgdGhlIHRvcCB0ZXJtcyBmcm9tIGVucmljaG1lbnQgYW5hbHlzaXMgcmVzdWx0OgpgYGB7ciB0bl9kb3duX2NsZWFuLCBtZXNzYWdlPUZBTFNFfQoKdG5fZG93biA8LSBwcm9jZXNzR1NFQSgidG5fZG93bi50c3YiKQoKIyBEaXNwbGF5IHJlc3VsdHMKa25pdHI6OmthYmxlKGhlYWQodG5fZG93biksIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSAyOiBUb3AgdGVybXMgb2YgZG93bnJlZ3VsYXRlZCBnZW5lcyBmb3IgVHVtb3IgdnMuIE5vcm1hbCB0aXNzdWUgY29tcGFyaXNvbiIpICU+JSBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCJzdHJpcGVkIikKYGBgCgoKIyMgTWV0YXN0YXNlcyB2cy4gTm9ybWFsIHRpc3N1ZQoKV2Ugbm93IHBlcmZvcm0gdGhlIHNhbWUgc3RlcHMgZm9yIHRoZSBNZXRhc3Rhc2VzIHZzLiBOb3JtYWwgdGlzc3VlIGNvbXBhcmlzb24uIEZpcnN0LCBjcmVhdGUgdGhlIHJhbmtlZCBnZW5lIGxpc3QgYmFzZWQgb24gdGhlIHJhbmsgZm9ybXVsYSBpbmRpY2F0ZWQgcHJldmlvdXNseS4KYGBge3IgY3JlYXRlIHJhbmtlZCBnZW5lIGxpc3QgZm9yIE0gdnMgTiwgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0naGlkZScsIG1lc3NhZ2U9RkFMU0V9CnJhbmtlZF9tbl9saXN0IDwtIGRhdGEuZnJhbWUoR2VuZU5hbWUgPSByb3duYW1lcyhxbGZfbW5faGl0cyR0YWJsZSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmsgPSAtbG9nMTAocWxmX21uX2hpdHMkdGFibGUkUFZhbHVlKSAqIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaWduKHFsZl9tbl9oaXRzJHRhYmxlJGxvZ0ZDKSkKcmFua2VkX21uX2xpc3QgPC0gcmFua2VkX21uX2xpc3Rbb3JkZXIocmFua2VkX21uX2xpc3QkcmFuaywgZGVjcmVhc2luZyA9IFRSVUUpLF0KYGBgCgpUaGVuLCBzYXZlIHRoZSBsaXN0IGluIHJuayBmaWxlLiBUaGUgZGF0YSB3aWxsIGJlIHB1c2hlZCBvbnRvIEdpdGh1YiBpbiB0aGUgImRhdGEiIGZvbGRlciwgc28gdGhpcyBjb2RlIGNodW5rIHdvdWxkIG5vdCBhY3R1YWxseSBydW4uCmBgYHtyIG91dHB1dCByYW5rZWQgbW4gbGlzdCwgZXZhbCA9IEZBTFNFfQp3cml0ZS50YWJsZShyYW5rZWRfbW5fbGlzdCwgZmlsZSA9ICJkYXRhL3JhbmtlZF9tbl9saXN0LnJuayIsIHNlcCA9ICJcdCIsIAogICAgICAgICAgICBxdW90ZSA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgpOZXh0LCB3ZSBtb3ZlIHRvIHRoZSBHU0VBIHZlcnNpb24gNC4zLjIgYXBwbGljYXRpb24gb24gbGFwdG9wIHRvIHBlcmZvcm0gdGhlIG5vbi10aHJlc2hvbGRlZCBlbnJpY2htZW50IGFuYWx5c2lzLgoKVGhlIHBhcmFtZXRlcnMgYmVpbmcgdXNlZCBhcmUgYXMgZm9sbG93aW5nOgoqIE1heGltdW0gZ2VuZXNldCBzaXplOiAyMDAKKiBNaW5pbXVtIGdlbmVzZXQgc2l6ZTogMTUKKiBOdW1iZXIgb2YgcGVybXV0YXRpb25zOiAxMDAwCiogTm8gY29sbGFwc2UKCjxicj4KX18qKlN1bW1hcml6ZSBvZiBlbnJpY2htZW50IHJlc3VsdHMuKipfXwo8YnI+CgpGb3IgdGhlIHVwcmVndWxhdGVkIGdlbmVzLCB0aGUgc3VtbWFyaXplZCByZXN1bHRzIGFyZSBhcyBmb2xsb3dpbmc6CiogMzYxOCBvdXQgb2YgNTk3OCBnZW5lIHNldHMgYXJlIHVwcmVndWxhdGVkIGluIHVwcmVndWxhdGVkIGdlbmVzCiogMTcyMSBnZW5lIHNldHMgYXJlIHNpZ25pZmljYW50IGF0IEZEUiA8IDI1JQoqIDgyNCBnZW5lIHNldHMgYXJlIHNpZ25pZmljYW50bHkgZW5yaWNoZWQgYXQgbm9taW5hbCBwdmFsdWUgPCAxJQoqIDEzMjIgZ2VuZSBzZXRzIGFyZSBzaWduaWZpY2FudGx5IGVucmljaGVkIGF0IG5vbWluYWwgcHZhbHVlIDwgNSUKCgpUaGUgZm9sbG93aW5nIHRhYmxlIGRpc3BsYXlzIHRoZSB0b3AgdGVybXMgZm9yIHRoZSB1cHJlZ3VsYXRlZCBnZW5lcyBmb3IgTWV0YXN0YXNlcyB2cy4gTm9ybWFsIHRpc3N1ZSBjb21wYXJpc29uLgpgYGB7ciBtbl91cF9jbGVhbiwgbWVzc2FnZT1GQUxTRX0KCm1uX3VwIDwtIHByb2Nlc3NHU0VBKCJtbl91cC50c3YiKQoKIyBEaXNwbGF5IHJlc3VsdHMKa25pdHI6OmthYmxlKGhlYWQobW5fdXApLCBmb3JtYXQgPSAiaHRtbCIsIGNhcHRpb24gPSAiVGFibGUgMzogVG9wIHRlcm1zIG9mIHVwcmVndWxhdGVkIGdlbmVzIGZvciBNZXRhc3Rhc2VzIHZzLiBOb3JtYWwgdGlzc3VlIGNvbXBhcmlzb24iKSAlPiUga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZygic3RyaXBlZCIpCmBgYAoKCkZvciB0aGUgZG93bnJlZ3VsYXRlZCBnZW5lcywgdGhlIHN1bW1hcml6ZWQgcmVzdWx0cyBhcmUgYXMgZm9sbG93aW5nOgoqIDIzNjAgb3V0IG9mIDU5NzggZ2VuZSBzZXRzIGFyZSB1cHJlZ3VsYXRlZCBpbiBkb3ducmVndWxhdGVkIGdlbmVzCiogMzIyIGdlbmUgc2V0cyBhcmUgc2lnbmlmaWNhbnRseSBlbnJpY2hlZCBhdCBGRFIgPCAyNSUKKiAxODIgZ2VuZSBzZXRzIGFyZSBzaWduaWZpY2FudGx5IGVucmljaGVkIGF0IG5vbWluYWwgcHZhbHVlIDwgMSUKKiAzODYgZ2VuZSBzZXRzIGFyZSBzaWduaWZpY2FudGx5IGVucmljaGVkIGF0IG5vbWluYWwgcHZhbHVlIDwgNSUKCkFuZCB0aGUgdG9wIHRlcm1zIGZvciB0aGUgZG93bnJlZ3VsYXRlZCBnZW5lczoKYGBge3IgbW5fZG93bl9jbGVhbiwgbWVzc2FnZT1GQUxTRX0KbW5fZG93biA8LSBwcm9jZXNzR1NFQSgibW5fZG93bi50c3YiKQoKIyBEaXNwbGF5IHJlc3VsdHMKa25pdHI6OmthYmxlKGhlYWQobW5fZG93biksIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSA0OiBUb3AgdGVybXMgb2YgZG93bnJlZ3VsYXRlZCBnZW5lcyBmb3IgTWV0YXN0YXNlcyB2cy4gTm9ybWFsIHRpc3N1ZSBjb21wYXJpc29uIikgJT4lIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoInN0cmlwZWQiKQpgYGAKCjxicj4KX18qKkhvdyBkbyB0aGVzZSByZXN1bHRzIGNvbXBhcmUgdG8gdGhlIHJlc3VsdHMgZnJvbSB0aGUgdGhyZXNob2xkZWQgYW5hbHlzaXMgaW4gQXNzaWdubWVudCAjMj8gQ29tcGFyZSBxdWFsaXRhdGl2ZWx5LiBJcyB0aGlzIGEgc3RyYWlnaHQgZm9yd2FyZCBjb21wYXJpc29uPyBXaHkgb3Igd2h5IG5vdD8qKl9fCjxicj4KCkZvciBUdW1vciB2cy4gTm9ybWFsIHRpc3N1ZSBjb21wYXJpc29uIGdyb3VwLCB0aGUgR1NFQSByZXN1bHRzIGZvciB0aGUgdXByZWd1bGF0ZWQgZ2VuZXMgYXJlIHZlcnkgc2ltaWxhciB0byB0aGUgdGhyZXNob2xkZWQgYW5hbHlzaXMgcGVyZm9ybWVkIHVzaW5nIGc6UHJvZmlsZXIgaW4gQXNzaWdubWVudCAyLCB3aGVyZSB0aGUgdG9wIHRlcm1zIGluY2x1ZGUgY2VsbCBqdW5jdGlvbiBvcmdhbml6YXRpb24sIGFuZCBpbiBBc3NpZ25tZW50IDIgdGhlIGNlbGwganVuY3Rpb24gYXNzZW1ibHkgaXMgYWxzbyBsaXN0ZWQuIEhvd2V2ZXIsIHRoZXJlIGlzIGEgbGFyZ2UgZGlmZmVyZW5jZSBpbiB0aGUgZGF0YWJhc2Ugc291cmNlcyB3aGVyZSB0ZXJtcyBzaG93IHVwLiBGb3IgdGhyZXNob2xkZWQgYW5hbHlzaXMgaW4gQXNzaWdubWVudCAyLCBtb3N0IG9mIHRoZSB0b3AgdGVybXMgcmV0dXJuZWQgYXJlIGZyb20gR09CUCBkYXRhIHNvdXJjZSwgd2hlcmVhcyBpbiB0aGUgbm9uLXRocmVzaG9sZGVkIGFuYWx5c2lzLCB0aGUgdG9wIHRlcm1zIGluY2x1ZGUgdmFyaW91cyBkYXRhIHNvdXJjZXMsIGluY2x1ZGluZyBHT0JQLCBSRUFDVE9NRSwgYW5kIE1TSUdEQkhBTExNQVJLLCBhcyBzaG93biBpbiBUYWJsZSAxLiBGb3IgdGhlIGRvd25yZWd1bGF0ZWQgZ2VuZXMsIHRoZSByZXN1bHRzIGFyZSB2ZXJ5IHNpbWlsYXIgdG8gQTIgcmVzdWx0cyBhcyB3ZWxsLCB3aGVyZSBib3RoIHRoZSB0b3AgdGVybXMgYXJlIGNlbGx1bGFyIHJlc3BpcmF0aW9uIGFuZCBhZXJvYmljIHJlc3BpcmF0aW9uLiBUZXJtcyBzdWNoIGFzIHByb3RvbiBtb3RpdmUgZm9yY2UtZHJpdmVuIEFUUCBzeW50aGVzaXMgYWxzbyBvY2N1cnMgdG8gYmUgb25lIG9mIHRoZSBtb3N0IHNpZ25pZmljYW50IHRlcm1zIGluIGJvdGggYW5hbHlzaXMuIAoKRm9yIE1ldGFzdGFzZXMgdnMuIE5vcm1hbCB0aXNzdWUgY29tcGFyaXNvbiBncm91cCwgdGhlIEdTRUEgcmVzdWx0cyBhbmQgZzpQcm9maWxlciByZXN1bHRzIGFyZSB2ZXJ5IGRpZmZlcmVudCBmb3IgdGhlIHVwLXJlZ3VsYXRlZCBnZW5lcywgYnV0IGFyZSBxdWl0ZSBzaW1pbGFyIGZvciB0aGUgZG93bnJlZ3VsYXRlZCBnZW5lcy4gQm90aCBjZWxsdWxhciByZXNwaXJhdGlvbiBhbmQgYWVyb2JpYyByZXNwaXJhdGlvbiBzaG93ZWQgdXAgaW4gYm90aCBhbmFseXNpcyBhcyB0aGUgdG9wIHRlcm1zIHJldHVybmVkLiAKCkhvd2V2ZXIsIHRoaXMgaXMgbm90IGEgc3RyYWlnaHQgZm9yd2FyZCBjb21wYXJpc29uIGJlY2F1c2UgZzpQcm9maWxlciBhbmQgR1NFQSB1c2UgZGlmZmVyZW50IGFwcHJvYWNoZXMuIFRoZSBzaW1pbGFyaXR5IGluIHRoZSB0aGUgdG9wIHRlcm1zIGlzIGxpa2VseSBhdHRyaWJ1dGVkIHRvIHRoZSBzaWduaWZpY2FudCBvdmVycmVwcmVzZW50YXRpb24gb2YgY2VydGFpbiBnZW5lcy4KCgoKIyBWaXN1YWxpemUgR2VuZSBzZXQgRW5yaWNobWVudCBBbmFseXNpcyBpbiBDeXRvc2NhcGUKSW4gdGhpcyBzZWN0aW9uLCB3ZSB3aWxsIGltcG9ydCB0aGUgcmVzdWx0cyBmcm9tIEdTRUEgaW50byBDeXRvc2NhcGUgYW5kIHZpc3VhbGl6ZSB0aGUgZW5yaWNobWVudCByZXN1bHRzIGFzIGEgbmV0d29yay4gCgojIyBUdW1vciB2cy4gTm9ybWFsIHRpc3N1ZQoKIyMjIENyZWF0ZSBFbnJpY2htZW50IE1hcAo8YnI+Cl9fKioxLiBDcmVhdGUgYW4gZW5yaWNobWVudCBtYXAgLSBob3cgbWFueSBub2RlcyBhbmQgaG93IG1hbnkgZWRnZXMgaW4gdGhlIHJlc3VsdGluZyBtYXA/IFdoYXQgdGhyZXNob2xkcyB3ZXJlIHVzZWQgdG8gY3JlYXRlIHRoaXMgbWFwPyBNYWtlIHN1cmUgdG8gcmVjb3JkIGFsbCB0aHJlc2hvbGRzLiBJbmNsdWRlIGEgc2NyZWVuc2hvdCBvZiB5b3VyIG5ldHdvcmsgcHJpb3IgdG8gbWFudWFsIGxheW91dC4qKl9fCjxicj4KSW4gQ3l0b3NjYXBlLCB3ZSB1c2VkIEVucmljaG1lbnRtYXAgQXBwIHRvIGdlbmVyYXRlIHRoZSBuZXR3b3JrIGZyb20gR1NFQSByZXN1bHRzLiBBZnRlciBpbnN0YWxsaW5nIHRoZSBhcHAsIHdlIGNob29zZSB0aGUgQW5hbHlzaXMgVHlwZSBvcHRpb24gYXMgR1NFQSwgYW5kIHVwbG9hZCB0aGUgcmVzdWx0cyBmb3IgdXByZWd1bGF0ZWQgZ2VuZXMgYXMgRW5yaWNobWVudHMgUG9zIGlucHV0LCBhbmQgdGhlIHJlc3VsdHMgZm9yIGRvd25yZWd1bGF0ZWQgZ2VuZXMgYXMgRW5yaWNobWVudHMgTmVnIGlucHV0LiBXZSBhbHNvIHVwbG9hZGVkIHRoZSBjb3JyZXNwb25kaW5nIEdNVCBmaWxlIHdoaWNoIHdlIHVzZWQgaW4gR1NFQSBlbnJpY2htZW50IGFuYWx5c2lzLCBhcyB3ZWxsIGFzIHRoZSByYW5rZWQgZ2VuZSBsaXN0IGZpbGUgZ2VuZXJhdGVkIHByZXZpb3VzbHkuCgpBZnRlciBjbGlja2luZyBvbiAiU2hvdyBBZHZhbmNlZCBPcHRpb25zIiwgd2Ugc2V0IHRoZSBwYXJhbWV0ZXJzIGFzIHRoZSBmb2xsb3dpbmc6CiogRkRSIHEtdmFsdWUgY3V0b2ZmOiAwLjAxCiogcC12YWx1ZSBjdXRvZmY6IDAuMDUKKiBFZGdlIGN1dG9mZjogMC4zNzUKKiBFZGdlIGZpbHRlcmluZyBtZXRyaWM6IEphY2NhcmQgKyBPdmVybGFwIGNvbWJpbmVkCiogUGFyc2UgYmFkZXJsYWIgbmFtZXMgaW4gR01UIGZpbGU6IENoZWNrZWQKClRoZSBGRFIgcS12YWx1ZSBhbmQgcC12YWx1ZSBjdXRvZmZzIHdlcmUgc2V0IHRvIGJlIGNvbnNpc3RlbnQgd2l0aCB0aGUgY3V0b2ZmIHVzZWQgZnJvbSBBc3NpZ25tZW50IDIuIFRoZSAiRWRnZSBjdXRvZmYiIGFuZCAiRWRnZSBmaWx0ZXJpbmcgbWV0cmljIiBvcHRpb25zIGFyZSBkZWZhdWx0IHZhbHVlcyBpbiBDeXRvc2NhcGUsIHdpdGggSmFjY2FyZCBtZXRyaWMgbWVhc3VyaW5nIHRoZSBpbnRlcnNlY3Rpb24gb3ZlciB1bmlvbiBhbmQgdGhlIG92ZXJsYXAgbWV0cmljIG1lYXN1cmluZyBpbnRlcnNlY3Rpb24gb3ZlciB0aGUgbWluaW11bSBzaXplLi4gVGhlICJQYXJzZSBiYWRlciBsYWIgbmFtZXMgaW4gR01UIGZpbGUiIG9wdGlvbiBjYW4gcHJvdmlkZSBiZXR0ZXIgcmVhZGFiaWxpdHkuCgpUaGUgbmV0d29yayBnZW5lcmF0ZWQgaW5jbHVkZXMgMTI2IG5vZGVzIGFuZCA4MDkgZWRnZXMsIHdoZXJlIGVhY2ggbm9kZSBpbmRpY2F0ZXMgYSBHTyB0ZXJtIG91ciBnZW5lIGxpc3QgbWF5IGJlIGludm9sdmVkIGluLCBhbmQgZWRnZXMgaW5kaWNhdGVzIHRoZSByZWxhdGlvbnNoaXBzIGFtb25nIEdPIHRlcm1zLiBUaGUgdGVybXMgZm9yIHVwcmVndWxhdGVkIGdlbmVzIGFyZSBjb2xvcmVkIGluIHJlZCwgYW5kIHRoZSB0ZXJtcyBmb3IgZG93bnJlZ3VsYXRlZCBnZW5lcyBhcmUgY29sb3JlZCBpbiBibHVlLCBhcyBzaG93biBpbiBGaWd1cmUgMS4KCmBgYHtyIHRuX25ldHdvcmssIG91dC53aWR0aCA9ICIxMDAlIiwgZWNobyA9IEZBTFNFLCBmaWcuY2FwPSJGaWd1cmUgMS4gRW5yaWNobWVudCBtYXAgZ2VuZXJhdGVkIGZyb20gVHVtb3IgdnMuIE5vcm1hbCBjb21wYXJpc29uIGdyb3VwIEdTRUEgcmVzdWx0LiBQb3NpdGl2ZSBwaGVub3R5cGVzICh1cHJlZ3VsYXRlZCkgYXJlIGNvbG9yZWQgcmVkIGFuZCBuZWdhdGl2ZSBwaGVub3R5cGVzIChkb3ducmVndWxhdGVkKSBhcmUgY29sb3JlZCBibHVlLiJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJmaWd1cmVzL3RuLnBuZyIpCmBgYAoKIyMjIE5ldHdvcmsgQW5ub3RhdGlvbgo8YnI+Cl9fKioyLiBBbm5vdGF0ZSB5b3VyIG5ldHdvcmsgLSB3aGF0IHBhcmFtZXRlcnMgZGlkIHlvdSB1c2UgdG8gYW5ub3RhdGUgdGhlIG5ldHdvcmsuIElmIHlvdSBhcmUgdXNpbmcgdGhlIGRlZmF1bHQgcGFyYW1ldGVycyBtYWtlIHN1cmUgdG8gbGlzdCB0aGVtIGFzIHdlbGwuKipfXwo8YnI+CgpUbyBhbm5ub3RhdGUgdGhlIG5ldHdvcmssIHdlIHVzZWQgQXV0b0Fubm90YXRlIGFwcCB1c2luZyB0aGUgZm9sbG93aW5nIGRlZmF1bHQgc2V0dGluZ3M6CiogUHJldmVudCBjbHVzdGVyIG92ZXJsYXAKKiBjbHVzdGVyIGFsZ29yaXRobTogTUNMIENsdXN0ZXIKKiBsYWJlbCBjb2x1bW46IEdTX0RFU0NSCiogbGFiZWwgYWxnb3JpdGhtOiBXb3JkQ2xvdWQ6IEFkamFjZW50IFdvcmRzCiogbWF4IHdvcmRzIHBlciBsYWJlbDogMwoqIG1pbmltdW0gd29yZCBvY2N1cmVuY2U6IDEKKiBhZGphY2VudCB3b3JkIGJvbnVzOiA4CgpUaGVuIHdlIGFkZCB0aGUgbGVnZW5kIGFuZCBtYW51YWxseSBsYXlvdXQgdGhlIG5ldHdvcmsgdG8gbWFrZSBpdCBwdWJsaWNhdGlvbiByZWFkeS4KYGBge3IgdG5fZGVmYXVsdF9hbm5vdCwgb3V0LndpZHRoID0gIjEwMCUiLCBlY2hvID0gRkFMU0UsIGZpZy5jYXA9IkZpZ3VyZSAyLiBBbm5vdGF0ZWQgbmV0d29yayBvZiB0aGUgb3JpZ2luYWwgVHVtb3IgdnMuIE5vcm1hbCBuZXR3b3JrLiBDbHVzdGVycyBhcmUgcmUtbGF5b3V0IHRvIHByZXZlbnQgb3ZlcmxhcCBhbmQgaW1wcm92ZSByZWFkYWJpbGl0eS4ifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiZmlndXJlcy90bl9kZWZhdWx0X2Fubm90LnBuZyIpCmBgYAoKCiMjIyBDb2xsYXBzZSBOZXR3b3JrIHRvIFRoZW1lIE5ldHdvcmsKCkluIHRoaXMgc2VjdGlvbiwgd2UgY29sbGFwc2VkIHRoZSBuZXR3b3JrIHRvIGEgdGhlbWUgbmV0d29yay4KCjxicj4KX18qKjMuIFdoYXQgYXJlIHRoZSBtYWpvciB0aGVtZXMgcHJlc2VudCBpbiB0aGlzIGFuYWx5c2lzPyBEbyB0aGV5IGZpdCB3aXRoIHRoZSBtb2RlbD8gQXJlIHRoZXJlIGFueSBub3ZlbCBwYXRod2F5cyBvciB0aGVtZXM/KipfXwo8YnI+CgpUaGUgbWFqb3IgdGhlbWVzIHByZXNlbnQgaW4gdGhpcyBhbmFseXNpcyBpbmNsdWVzIHVwcmVndWxhdGVkIHBhdGh3YXlzIHN1Y2ggYXMgZW5kb2dlbm91cyBwZXB0aWRlIGFudGlnZW4sIHNraW4gZXBpZGVybWlzIGRldmVsb3BtZW50LCBhbmQgdGhlIGRvd25yZWd1bGF0ZWQgcGF0aHdheXMgc3VjaCBhcyBjb3VwbGVkIGVsZWN0cm9uIHRyYW5zcG9ydCBhbmQgbWFueSBtb3JlIGFzIHNob3duIGluIEZpZ3VyZSAzIGJlbG93LiBJdCBpcyBjb25zaWRlcmVkIHRvIGZpdCB0aGUgbW9kZWwgYW5kIGFncmVlIHdpdGggdGhlIHJlc3VsdHMgYnkgdGhlIGF1dGhvcnMgb2YgdGhlIG9yaWdpbmFsIHB1YmxpY2F0aW9uLCBzaW5jZSB0aGUgdGVybSAiTWlybmEgcmVndWxhdGlvbiBvZiBwNTMgcGF0aHdheSBpbiBwcm9zdGF0ZSBjYW5jZXIiIHdhcyBhbHNvIG9ic2VydmVkIGFzIGFuIHVwcmVndWxhdGVkIHRlcm0gaW4gdGhlIHRoZW1lIG5ldHdvcmssIHdoaWNoIHN1cHBvcnRzIHRoYXQgdGhlIGdlbmUgc2V0IGRvIGludm9sdmUgaW4gY2FuY2VyIHJlbGF0ZWQgcGF0aHdheXMuIFRoZXJlIGFyZSBtYW55ICJwNTMiIHJlbGF0ZWQgdGhlbWVzIHRoYXQgd2VyZSBzaG93biB0byBiZSB1cHJlZ3VsYXRlZCBpbiB0aGUgbmV0d29yaywgd2hpY2ggYXJlIGNvbnNpZGVyZWQgbm92ZWwgYW5kIG1pZ2h0IHByb3ZpZGUgbmV3IGluc2lnaHRzIGluIHRoZSBtZWNoYW5pc20gdGhhdCB3b3VsZCBkZXZlbG9wIGNhbmNlciwgYW5kIGFyZSB3b3J0aCBmdXJ0aGVyIGludmVzdGlnYXRpb24uCgpgYGB7ciB0bl9jb2xsYXBzZSwgb3V0LndpZHRoID0gIjEwMCUiLCBlY2hvID0gRkFMU0UsIGZpZy5jYXA9IkZpZ3VyZSAzLiBDb2xsYXBzZWQgYW5ub3RhdGVkIG5ldHdvcmsgb2YgdGhlIG9yaWdpbmFsIFR1bW9yIHZzLiBOb3JtYWwgbmV0d29yay4gVGhlIHRoZW1lIGhpZ2hsaXRoZWQgaW4geWVsbG93IGJveCBpcyBjYW5jZXIgcmVsYXRlZCwgd2hpY2ggZml0cyB0aGUgbW9kZWwuIFRoZSBuZXR3b3JrIGFsc28gaW5jbHVkZXMgbXVsdGlwbGUgcDUzIHJlbGF0ZWQgdGhlbWVzLCB3aGljaCBhcmUgY29uc2lkZXJlZCBub3ZlbCBhbmQgbWlnaHQgcHJvdmlkZSBmdXJ0aGVyIGluc2lnaHRzIGluIGNhbmNlciBtZWNoYW5pc20uIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImZpZ3VyZXMvdG5fY29sbGFwc2UucG5nIikKYGBgCgoKIyMgTWV0YXN0YXNlcyB2cy4gTm9ybWFsIHRpc3N1ZQoKV2Ugbm93IGFsc28gZ2VuZXJhdGUgdGhlIG5ldHdvcmsgZm9yIE1ldGFzdGFzZXMgdnMuIE5vcm1hbCB0aXNzdWUgZ3JvdXAuIFRoZSBuZXR3b3JrIGluY2x1ZGVzIDQ1OCBub2RlcyBhbmQgMjkxNSBlZGdlcywgd2hpY2ggaXMgYWJvdXQgMyB0aW1lcyBtb3JlIG5vZGVzIGFuZCBlZGdlcyBjb21wYXJlZCB0byB0aGUgbmV0d29yayBmb3IgVHVtb3IgdnMuIE5vcm1hbCB0aXNzdWUgZ3JvdXAuCgpgYGB7ciBtbl9uZXR3b3JrLCBvdXQud2lkdGggPSAiMTAwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmNhcD0iRmlndXJlIDQuIEVucmljaG1lbnQgbWFwIGdlbmVyYXRlZCBmcm9tIE1ldGFzdGFzZXMgdnMuIE5vcm1hbCBjb21wYXJpc29uIGdyb3VwIEdTRUEgcmVzdWx0LiBQb3NpdGl2ZSBwaGVub3R5cGVzICh1cHJlZ3VsYXRlZCkgYXJlIGNvbG9yZWQgcmVkIGFuZCBuZWdhdGl2ZSBwaGVub3R5cGVzIChkb3ducmVndWxhdGVkKSBhcmUgY29sb3JlZCBibHVlLiJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJmaWd1cmVzL21uLnBuZyIpCmBgYAoKIyMjIE5ldHdvcmsgQW5ub3RhdGlvbgoKPGJyPgpfXyoqMi4gQW5ub3RhdGUgeW91ciBuZXR3b3JrIC0gd2hhdCBwYXJhbWV0ZXJzIGRpZCB5b3UgdXNlIHRvIGFubm90YXRlIHRoZSBuZXR3b3JrLiBJZiB5b3UgYXJlIHVzaW5nIHRoZSBkZWZhdWx0IHBhcmFtZXRlcnMgbWFrZSBzdXJlIHRvIGxpc3QgdGhlbSBhcyB3ZWxsLioqX18KPGJyPgoKVG8gYW5ubm90YXRlIHRoZSBuZXR3b3JrLCB3ZSB1c2VkIEF1dG9Bbm5vdGF0ZSBhcHAgdXNpbmcgdGhlIGZvbGxvd2luZyBkZWZhdWx0IHNldHRpbmdzOgoqIFByZXZlbnQgY2x1c3RlciBvdmVybGFwCiogY2x1c3RlciBhbGdvcml0aG06IE1DTCBDbHVzdGVyCiogbGFiZWwgY29sdW1uOiBHU19ERVNDUgoqIGxhYmVsIGFsZ29yaXRobTogV29yZENsb3VkOiBBZGphY2VudCBXb3JkcwoqIG1heCB3b3JkcyBwZXIgbGFiZWw6IDMKKiBtaW5pbXVtIHdvcmQgb2NjdXJlbmNlOiAxCiogYWRqYWNlbnQgd29yZCBib251czogOAoKVGhlbiB3ZSBhZGQgdGhlIGxlZ2VuZCB0byBtYWtlIGl0IHB1YmxpY2F0aW9uIHJlYWR5LgpgYGB7ciBtbl9kZWZhdWx0X2Fubm90LCBvdXQud2lkdGggPSAiMTAwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmNhcD0iRmlndXJlIDUuIEFubm90YXRlZCBuZXR3b3JrIG9mIHRoZSBvcmlnaW5hbCBNZXRhc3Rhc2VzIHZzLiBOb3JtYWwgbmV0d29yay4gQ2x1c3RlcnMgYXJlIHJlLWxheW91dCB0byBwcmV2ZW50IG92ZXJsYXAgYW5kIGltcHJvdmUgcmVhZGFiaWxpdHkuIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImZpZ3VyZXMvbW5fYW5ub3QucG5nIikKYGBgCgoKIyMjIENvbGxhcHNlIE5ldHdvcmsgdG8gVGhlbWUgTmV0d29yawoKSW4gdGhpcyBzZWN0aW9uLCB3ZSBjb2xsYXBzZWQgdGhlIG5ldHdvcmsgdG8gYSB0aGVtZSBuZXR3b3JrLgoKPGJyPgpfXyoqMy4gV2hhdCBhcmUgdGhlIG1ham9yIHRoZW1lcyBwcmVzZW50IGluIHRoaXMgYW5hbHlzaXM/IERvIHRoZXkgZml0IHdpdGggdGhlIG1vZGVsPyBBcmUgdGhlcmUgYW55IG5vdmVsIHBhdGh3YXlzIG9yIHRoZW1lcz8qKl9fCjxicj4KClRoZSBtYWpvciB0aGVtZXMgYXJlIGRpc3BsYXllZCBpbiBGaWd1cmUgNiBiZWxvdy4gVGhleSBmaXQgdGhlIG1vZGVsIGJlY2F1c2UgdGhlIG1ham9yIHRoZW1lcyBtYXRoY2VzIHdpdGggdGhlIHRvcCB0ZXJtcyByZXR1cm5lZCBmcm9tIEdTRUEgYW5kIHRocmVzaG9sZGVkIGFuYWx5c2lzIHJlc3VsdHMsIHN1Y2ggYXMgVC1jZWxsIHJlY2VwdG9yIChUQ1IpLCB3aGljaCBpcyB0aGUgbGFyZ2VzdCB0aGVtZSBpbiB0aGUgdGhlbWUgbmV0d29yaywgYW5kIHRoZSB0ZXJtICJULWNlbGwgYWN0aXZhdGlvbiIgYWxzbyBzaG93ZWQgdXAgaW4gdGhlIHRocmVzaG9sZGVkIGFuYWx5c2lzLiBUaGlzIHdvdWxkIGFsc28gYmUgY29uc2lkZXJlZCBhcyBhIG5vdmVsIHRoZW1lIGJlY2F1c2UgdGhlIGF1dGhvcnMgZGlkIG5vdCBkaXNjdXNzZWQgYWJvdXQgVC1jZWxsIHJlZ3VsYXRpb24gd2l0aCBodW1hbiBjYW5jZXIgbWVjaGFuaXNtLCB3aGljaCBpcyB3b3J0aCBmdXJ0aGVyIGludmVzdGlnYXRpb24uCmBgYHtyIG1uX2NvbGxhcHNlLCBvdXQud2lkdGggPSAiMTAwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmNhcD0iRmlndXJlIDYuIENvbGxhcHNlZCBhbm5vdGF0ZWQgbmV0d29yayBvZiB0aGUgb3JpZ2luYWwgTWV0YXN0YXNlcyB2cy4gTm9ybWFsIG5ldHdvcmsuIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImZpZ3VyZXMvbW5fY29sbGFwc2UucG5nIikKYGBgCgoKCiMgSW50ZXJwcmV0YXRpb24gYW5kIGRldGFpbGVkIHZpZXcgb2YgcmVzdWx0cwo8YnI+Cl9fKipEbyB0aGUgZW5yaWNobWVudCByZXN1bHRzIHN1cHBvcnQgY29uY2x1c2lvbnMgb3IgbWVjaGFuaXNtIGRpc2N1c3NlZCBpbiB0aGUgb3JpZ2luYWwgcGFwZXI/IEhvdyBkbyB0aGVzZSByZXN1bHRzIGRpZmZlciBmcm9tIHRoZSByZXN1bHRzIHlvdSBnb3QgZnJvbSBBc3NpZ25tZW50ICMyIHRocmVzaG9sZGVkIG1ldGhvZHM/IENhbiB5b3UgZmluZCBldmlkZW5jZSwgaS5lLiBwdWJsaWNhdGlvbnMsIHRvIHN1cHBvcnQgc29tZSBvZiB0aGUgcmVzdWx0cyB0aGF0IHlvdSBzZWUuIEhvdyBkb2VzIHRoaXMgZXZpZGVuY2Ugc3VwcG9ydCB5b3VyIHJlc3VsdD8qKl9fCjxicj4KVGhlIGVucmljaG1lbnQgcmVzdWx0cyBmcm9tIEdTRUEgc3VwcG9ydHMgdGhlIG1lY2hhbmlzbSBkaXNjdXNzZWQgaW4gdGhlIG9yaWdpbmFsIHBhcGVyLiBJbiB0aGUgb3JpZ2luYWwgcGFwZXIsIHRoZSBhdXRob3JzIHByZWRpY3RlZCB0aGF0IHRoZSB0dW1vcnMgd291bGQgaGF2ZSBURnMgdGhhdCBpbnRlcmFjdCB3aXRoIHRoZSBNQVBLIHBhdGh3YXkgYW5kIHJlZ3VsYXRlIGdlbmUgZXhwcmVzc2lvbiBpbiBhIHdheSB0aGF0IGlzIHJlbGV2YW50IHRvIHRoZSBkZXZlbG9wbWVudCBhbmQgcHJvZ3Jlc3Npb24gb2YgY2FuY2VyLCBhbmQgaW5kZWVkIHRoZXkgZm91bmQgdGhhdCBURnMgaW4gdGhlIE1BUEsgcGF0aHdheSBhcmUgYWN0aXZlbHkgYm91bmQgc2lnbmlmaWNhbnRseSBtb3JlIGluIHR1bW9yIGFuZCBtZXRhc3Rhc2VzIHRoYW4gaW4gbm9ybWFsIHRpc3N1ZS4gQWNjb3JkaW5nIHRvIHRoZSBwdWJsaWNhdGlvbiAiVHJhbnNjcmlwdGlvbmFsIHJlZ3VsYXRpb24gYnkgcDUzIiAoQGJlY2tlcm1hbjIwMTBhKSwgcDUzIGlzIGFuIGltcG9ydGFudCB0cmFuc2NyaXB0aW9uIGZhY3RvciB0aGF0IHJlZ3VsYXRlcyBodW5kcmVkcyBvZiBjZWxscycgUk5BIHBvbHltZXJhc2UgSUkgdHJhbnNjcmliZWQgZ2VuZXMuIEJ5IHB1YmxpY2F0aW9uICJUaGUgZnVuY3Rpb25hbCBpbnRlcmFjdGlvbnMgYmV0d2VlbiB0aGUgcDUzIGFuZCBNQVBLIHNpZ25hbGluZyBwYXRod2F5cyIgKEBzMjAwNGEpLCBwNTMgaXMgaWRlbnRpZmllZCBhcyBhIHR1bW9yIHN1cHJlc3NvciBwcm90ZWluIHRvIGJlIGZ1bmN0aW9uYWxseSBpbnRlcmFjdCB3aXRoIHRoZSBNQVBLIHBhdGh3YXksIHdoaWNoIGZ1cnRoZXIgc3VwcG9ydHMgb3VyIHJlc3VsdHMuCgoKCiMgUG9zdCBBbmFseXNpcwo8YnI+Cl9fKipBZGQgYSBwb3N0IGFuYWx5c2lzIHRvIHlvdXIgbWFpbiBuZXR3b3JrIHVzaW5nIHNwZWNpZmljIHRyYW5zY3JpcHRpb24gZmFjdG9ycywgbWljcm9STkFzIG9yIGRydWdzLiBJbmNsdWRlIHRoZSByZWFzb24gd2h5IHlvdSBjaG9zZSB0aGUgc3BlY2lmaWMgbWlScywgVEZzIG9yIGRydWdzIChpLmUgcHVibGljYXRpb25zIGluZGljYXRpbmcgdGhhdCB0aGV5IG1pZ2h0IGJlIHJlbGF0ZWQgdG8geW91ciBtb2RlbCkuIFdoYXQgZG9lcyB0aGlzIHBvc3QgYW5hbHlzaXMgc2hvdz8qKl9fCjxicj4KCkkgYW0gY3VyaW91cyBvbiB0aGUgcDUzIHJlbGF0ZWQgdGVybXMgdGhhdCBzaG93ZWQgdXAgaW4gdGhlIFR1bW9yIHZzLiBOb3JtYWwgdGlzc3VlIGNvbXBhcmlzb24gYW5kIHdvdWxkIGxpa2UgdG8gaW52ZXN0aWdhdGUgd2hldGhlciB0aGUgaW5jcmVhc2VkIGFtb3VudCBvZiBURnMgdGhlIGF1dGhvcnMgZGV0ZWN0ZWQgaW4gZXhwZXJpbWVudCB3ZXJlIGFjdHVhbGx5IHA1MyBpbiB0aGUgdHVtb3Igc2FtcGxlcywgc28gSSB3aWxsIHVzZSBwNTMgYXMgdGhlIFRGIHRvIHBlcmZvcm0gYSBQb3N0IChLbm93biBTaWduYXR1cmVzKSBhbmFseXNpcyBvbiBvdXIgbmV0d29yay4gSSBjaG9zZSBwNTMgYmVjYXVzZSBpdCB3YXMgYSB0cmFuc2NyaXB0aW9uYWwgZmFjdG9yIGludm9sdmVkIGluIE1BUEsgcGF0aHdheSwgd2hpY2ggaXMgcmVsYXRlZCB0byBjYW5jZXIsIGFzIGluZGljYXRlZCBmcm9tIHRoZSBwdWJsaWNhdGlvbiAiVGhlIGZ1bmN0aW9uYWwgaW50ZXJhY3Rpb25zIGJldHdlZW4gdGhlIHA1MyBhbmQgTUFQSyBzaWduYWxpbmcgcGF0aHdheXMiIChAczIwMDRhKS4KCldpdGhpbiBDeXRvc2NhcGUgRW5yaWNobWVudE1hcCBhcHAsIHdlIGRvd25sb2FkZWQgdGhlIGN1cnJlbnQgcmVsZWFzZSBvZiBodW1hbiBzeW1ib2wgdHJhbnNjcmlwdGlvbiBmYWN0b3JzIEdNVCBmaWxlLCBhbmQgdGhlbiBzZWxlY3Qgb25seSB0aGUgZm9sbG93aW5nIHR3byBzaWduYXR1cmUgZ2VuZSBzZXRzIHNpbmNlIHdlIGFyZSBvbmx5IGludGVyZXN0ZWQgaW4gcDUzOgoqIFA1M18wMi52MjAyMy4xLkhzCiogUDUzX0RFQ0FNRVJfUTIudjIwMjMuMS5IcwoKV2UgdXNlZCB0aGUgTWFubi1XaGl0bmV5IChUd28tU2lkZWQpIHRlc3Rpbmcgd2l0aCAwLjAxIGN1dG9mZiB0byBpbnZlc3RpZ2F0ZSB3aGV0aGVyIHRoZSBnZW5lcyBpbiB0aGUgc2lnbmF0dXJlIHNldHMgd2VyZSBmb3VuZCBtb3N0bHkgYXQgdGhlIGJvdHRvbSBvciB0aGUgdG9wIG9mIG91ciByYW5rZWQgZ2VuZSBsaXN0LgoKVGhlIG5ldHdvcmsgZ2VuZXJhdGVkIGlzIHNob3duIGJlbG93LCB3aGVyZSB0aGUgdGVybXMgUDUzIFRSQU5TQ1JJUFRJT05BTCBHRU5FIE5FVFdPUkssIERJUkVDVCBQNTMgRUZGRUNUT1JTIGFuZCBIQUxMTUFSSyBBTExPR1JBRlQgUkVKRUNUSU9OIGFyZSBsaW5rZWQgdG8gdGhlIHR3byBzaWduYXR1cmUgZ2VuZSBzZXRzLgoKYGBge3IgcG9zdF9hbmFseXNpcywgb3V0LndpZHRoID0gIjEwMCUiLCBlY2hvID0gRkFMU0UsIGZpZy5jYXA9IkZpZ3VyZSA3LiBQb3N0IGFuYWx5c2lzIG5ldHdvcmsgb24gVHVtb3IgdnMuIE5vcm1hbCB0aXNzdWUgY29tcGFyaXNvbi4gdGhlIHRlcm1zIFA1MyBUUkFOU0NSSVBUSU9OQUwgR0VORSBORVRXT1JLLCBESVJFQ1QgUDUzIEVGRkVDVE9SUyBhbmQgSEFMTE1BUksgQUxMT0dSQUZUIFJFSkVDVElPTiBhcmUgbGlua2VkIHRvIHRoZSB0d28gc2lnbmF0dXJlIGdlbmUgc2V0cy4gVGhlIGRvdHRlZCBsaW5lIGxpbmtpbmcgdGhlIHRhcmdldCB0ZXJtcyBhbmQgc2lnbmF0dXJlIGRhdGEgc2V0cyBpbmRpY2F0ZSBhIHNpZ25pZmljYW5jZSBsZXZlbCA8IDAuMDEuIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImZpZ3VyZXMvcDUzX3Bvc3QucG5nIikKYGBgCgpGcm9tIHRoZSBuZXR3b3JrLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGxpbmtlZCB0YXJnZXQgdGVybXMgYXJlIGhpZ2hseSBzaWduaWZpY2FudCB0byB0aGUgc2lnbmF0dXJlIGRhdGEgc2V0cywgd2l0aCBhIHNpZ25pZmljYW5jZSBsZXZlbCBvZiA8IDAuMDEuIEEgZ2VuZSBuYW1lZCAiRkFTIiBpcyBub3RpY2FibGUsIHdoZXJlIGl0IGlzIG9uZSBvZiB0aGUgdG9wIHRocmVlIGdlbmVzIHJhbmtlZCBpbiBhbGwgdGhyZWUgdGVybXMsIGFzIHNob3duIGluIFRhYmxlIDUuCgpgYGB7ciBGQVNfdGFibGVfYSwgbWVzc2FnZT1GQUxTRX0KZGlyZWN0X3A1MyA8LSByZWFkLnRhYmxlKCJkYXRhL2RpcmVjdF9wNTNfZWZmZWN0b3JzLnR4dCIsIHNlcCA9ICJcdCIsIGhlYWRlciA9IFRSVUUpCgojIERpc3BsYXkgcmVzdWx0cwprbml0cjo6a2FibGUoaGVhZChkaXJlY3RfcDUzWywgMTozXSksIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSA1OiAoYSkgVG9wIHJhbmtlZCBnZW5lcyBmb3IgdGhlIHRlcm0gRElSRUNUIFA1MyBFRkZFQ1RPUlMuIEZBUyBnZW5lIGlzIGhpZ2hsaWdodGVkIGFzIG9uZSBvZiB0aGUgdG9wIGdlbmVzIGluIHRoZSBsaXN0LiIpICU+JSAKICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCJzdHJpcGVkIikgJT4lIAogIGthYmxlRXh0cmE6OnJvd19zcGVjKDMsIGJhY2tncm91bmQgPSAieWVsbG93IikKYGBgCgpgYGB7ciBGQVNfdGFibGVfYiwgbWVzc2FnZT1GQUxTRX0KcDUzX3RnbiA8LSByZWFkLnRhYmxlKCJkYXRhL3A1M190cmFuc2NyaXB0aW9uYWxfZ2VuZV9uZXR3b3JrLnR4dCIsIHNlcCA9ICJcdCIsIGhlYWRlciA9IFRSVUUpCgojIERpc3BsYXkgcmVzdWx0cwprbml0cjo6a2FibGUoaGVhZChwNTNfdGduWywgMTozXSksIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSA1OiAoYikgVG9wIHJhbmtlZCBnZW5lcyBmb3IgdGhlIHRlcm0gRFA1MyBUUkFOU0NSSVBUSU9OQUwgR0VORSBORVRXT1JLLiBGQVMgZ2VuZSBpcyBoaWdobGlnaHRlZCBhcyBvbmUgb2YgdGhlIHRvcCBnZW5lcyBpbiB0aGUgbGlzdC4iKSAlPiUgCiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZygic3RyaXBlZCIpICU+JSAKICBrYWJsZUV4dHJhOjpyb3dfc3BlYygyLCBiYWNrZ3JvdW5kID0gInllbGxvdyIpCmBgYAoKYGBge3IgRkFTX3RhYmxlX2MsIG1lc3NhZ2U9RkFMU0V9CmhhbGxtYXJrIDwtIHJlYWQudGFibGUoImRhdGEvaGFsbG1hcmtfYWxsb2dyYWZ0X3JlamVjdGlvbi50eHQiLCBzZXAgPSAiXHQiLCBoZWFkZXIgPSBUUlVFKQoKIyBEaXNwbGF5IHJlc3VsdHMKa25pdHI6OmthYmxlKGhlYWQoaGFsbG1hcmtbLCAxOjNdKSwgZm9ybWF0ID0gImh0bWwiLCBjYXB0aW9uID0gIlRhYmxlIDU6IChjKSBUb3AgcmFua2VkIGdlbmVzIGZvciB0aGUgdGVybSBIQUxMTUFSSyBBTExPR1JBRlQgUkVKRUNUSU9OLiBGQVMgZ2VuZSBpcyBoaWdobGlnaHRlZCBhcyBvbmUgb2YgdGhlIHRvcCBnZW5lcyBpbiB0aGUgbGlzdC4iKSAlPiUgCiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZygic3RyaXBlZCIpICU+JSAKICBrYWJsZUV4dHJhOjpyb3dfc3BlYygxLCBiYWNrZ3JvdW5kID0gInllbGxvdyIpCmBgYAoKRkFTIGdlbmUgaXMgdGhlIGFwb3B0b3Npcy1tZWRpYXRpbmcgc3VyZmFjZSBhbnRpZ2VuLCB3aGljaCB0YXJnZXRzIFR1bW9yIE5jcm9zaXMgRmFjdG9yIFJlY2VwdG9yIFN1cGVyZmFtaWx5LiBBY2NvcmRpbmcgdG8gdGhlIHB1YmxpY2F0aW9uICJSZWd1bGF0aW9uIG9mIHRoZSBwNTMgdHJhbnNjcmlwdGlvbmFsIHJlc3BvbnNlIGJ5IHN0cnVjdHVyYWxseSBkaXZlcnNlIGNvcmUgcHJvbW90ZXJzIiAoQG1vcmFjaGlzMjAxMGEpLCBwNTMgdGFyZ2V0IHByb21vdGVycyBhcmUgc3RydWN0dXJhbGx5IGRpdmVyc2UgYW5kIGRpc3BsYXkgcHJvbm91bmNlZCBkaWZmZXJlbmNlcyBpbiBSTkEgcG9seW1lcmFzZSBJSSAoUk5BUCBJSSkgb2NjdXBhbmN5IHdpdGggaGlnaCBsZXZlbCBvZiBGQVMgZ2VuZXMgaW4gdW5zdHJlc3NlZCBjZWxscy4gU2luY2UgaXQgd2FzIGRpc2N1c3NlZCB0aGF0IHA1MyBpcyBhbiBpbXBvcnRhbnQgdHJhbnNjcmlwdGlvbmFsIGZhY3RvciBpbnZvbHZlZCBpbiBNQVBLIHBhdGh3YXkgd2hpY2ggbWlnaHQgY2F1c2UgY2FuY2VyIGZvciBpdHMgbWlzcy1mdW5jdGlvbmluZywgZm9jdXNpbmcgbW9yZSBvbiB0aGUgRkFTIGdlbmUgYW5kIHRoZSBwNTMgbWVjaGFuaXNtIG1heSBwcm92aWRlIGZ1cnRoZXIgaW5zaWdodHMgb24gZGVzaWduaW5nIHRoZXJhcGllcy4KCgoKCiMgUmVmZXJlbmNlcwoKCgoKCgoKCgoKCgoKCgo=